├── .gitignore
├── README.md
├── ReleaseNotes.md
├── cv.md
├── description.md
├── doc
├── lesson07.md
├── video1.md
├── video2.1.md
├── video2.2.md
├── video2.3.md
├── video2.4.md
├── video3.md
├── video4.md
└── video5-vcs-git.md
├── graduation.md
├── pom.xml
└── src
└── main
└── java
└── ru
└── javawebinar
└── topjava
└── Main.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | out
3 | target
4 | *.iml
5 | log
6 | *.patch
7 |
8 |
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [Java Enterprise Online Project](https://javaops.ru/view/topjava)
2 | ===============================
3 | Разработка полнофункционального Spring/JPA Enterprise приложения c авторизацией и правами доступа на основе ролей с использованием наиболее популярных инструментов и технологий Java: Maven, Spring MVC, Security, JPA(Hibernate), REST(Jackson), Bootstrap (css,js), DataTables, jQuery + plugins, Java 8 Stream and Time API и хранением в базах данных Postgresql и HSQLDB.
4 |
5 | 
6 |
7 | Когда вы слышите что-то, вы забываете это.
8 | Когда вы видите что-то, вы запоминаете это.
9 | Но только когда вы начинаете делать это,
10 | вы начинаете понимать это
11 |
12 | Старинная китайская поговорка
13 |
14 | ## Описание и план проекта
15 | ### Демо разрабатываемого приложения
16 | ### [Изменения проекта (Release Notes)](ReleaseNotes.md)
17 | ### Требования к участникам, Wiki
18 | ### Составление резюме, подготовка к интервью, поиск работы
19 |
20 | Обновленное вводное занятие (обязательно смотреть все видео)
21 | ===============
22 | ##  1. [Вступление, история, команда, источники](doc/video1.md)
23 |
24 | ## Обзор наиболее востребованных технологий, которые будут изучаться на курсе TopJava
25 | ##  2.1. [Часть 1: инфраструктура](doc/video2.1.md)
26 |
27 | ##  2.2. [Часть 2: frameworks Spring, ORM](doc/video2.2.md)
28 |
29 | ##  2.3. [Часть 3: тренды](doc/video2.3.md)
30 |
31 | ##  2.3. [Часть 4: обзор разрабатываемого приложения](doc/video2.4.md)
32 |
33 | ##  3. [Рекомендуемые подходы к обучению на курсе](doc/video3.md)
34 |
35 | ##  4. [Структура приложения (многоуровневая архитектура)](doc/video4.md)
36 | ### [Демо приложения](http://javaops-demo.ru/topjava)
37 |
38 | ##  5. [Системы управления версиями. Git](doc/video5-vcs-git.md)
39 |
40 | ##  6. Работа с проектом (выполнять инструкции)
41 | - **ВНИМАНИЕ: выбирайте для проекта простой пусть без пробелов и русских букв, например, `c:\projects\topjava\` (Windows). Иначе впоследствии будут проблемы**
42 | - **Плагин Git Intergation уже не требуется, а вкладку `Version control` в IDEA переименовали в `Git`**
43 | - **C Ultimate IDEA сейчас сложности**, надеемся что временные.
44 | - Скачать IDEA и установливать плагины [можно по инструкции](https://github.com/JavaOPs/topjava/wiki/IDEA#download)
45 | - После Trial 30 дней [способы продлить использование](https://github.com/JavaOPs/topjava/wiki/IDEA#licence)
46 |
47 | Для переключения режима отображения изменений из вкладки `Commit` в `Git: Local Changes` нужно переключить `Settings/Preferences | Version Control | Commit | Use non-modal commit interface` или в контекстном меню вкладки `Commit`:
48 |
49 |  
50 |
51 | ### Патч [prepare_to_HW0.patch](https://drive.google.com/file/d/1LNPpu9OkuCpfpD8ZJHO-o0vwu49p2i5M) (скачать и положить в каталог вашего проекта)
52 |
53 | > Проект постоянно улучшается, поэтому видео иногда отличается от кода проекта. Изменения указываю после видео:
54 | > - переименовал класс `UserMealWithExceed` и его поле `exceed` в `UserMealWithExcess.excess`
55 | > - в `UserMeals/UserMealWithExcess` поля изменились на `private`
56 | > - обновил данные `UserMealsUtil.meals` и переименовал некоторые переменные, поля и методы
57 | > - добавил `UserMealWithExcess.toString()` и метод для выполнения _Optional домашнего задания_
58 | > - метод фильтрации в `TimeUtil` переименовал в `isBetweenHalfOpen` (также изменилась логика сравнения: `startTime` включается в интервал, а `endTime` - не включается)
59 |
60 | ### GitHub поменял политику: теперь пушить нужно через токен. IDEA предложит его сгенерировать при пуше, или можно [создать токен в настройках](https://www.jetbrains.com/help/idea/github.html#register-account)
61 | - [Способы авторизации в GitHub](https://topjava.ru/blog/vvedeniye-v-git-github-ustanovka-i-nastroyka#6)
62 |
63 | ## Инструкция по шагам (из видео):
64 | - Установить ПО (Git, JDK8, IntelliJ IDEA, Maven)
65 | - Создать аккаунт на GitHub
66 | - Сделать Fork **ЭТОГО** проекта (https://github.com/JavaOPs/topjava)
67 | - Сделать локальный репозиторий проекта:
68 |
69 |
70 | > Вместо Fork можно сделать [клонирование проекта](https://github.com/JavaOPs/topjava/wiki/Git#user-content-Клонирование-проекта): он не будет привязан к исходному https://github.com/JavaOPs/topjava и у него не будет истории.
71 |
72 | - Открыть и настроить проект в IDEA
73 | - Выставить кодировку UTF-8 в консоли
74 | - Поставить кодировку UTF-8
75 | - Опционально: поменять шрифт по умолчанию на DejaVu или на **новый [JetBrains Mono](https://habr.com/ru/company/jugru/news/t/484134/)**
76 | - По ходу видео сделать `Apply Patch...` скачанного патча `Prepare_to_HW0.patch`
77 | - Закоммитить и запушить изменения (`commit` + `push`)
78 | - Сделать ветку домашнего задания
79 | - Выполнить задание и залить на GitHub (`commit` + `push`)
80 | - Переключиться в основную ветку проекта `master`.
81 |
82 | ##  7. [Maven](https://drive.google.com/file/d/1qEJTwv9FNUQjx-y9MSydH01xaAne0-hu)
83 | - [Как установить Maven 3 на Ubuntu или Windows](https://devcolibri.com/как-установить-maven-3-на-ubuntu-или-windows/)
84 | - [Руководство по Maven](https://topjava.ru/blog/apache-maven-osnovy-1)
85 | - Wiki: [Apache Maven](https://ru.wikipedia.org/wiki/Apache_Maven)
86 | - [The Central Repository](http://search.maven.org)
87 | - Дополнительно:
88 | - [Мой Wiki по Maven](https://github.com/JavaOPs/topjava/wiki/Maven)
89 | - [Основы Maven](https://www.youtube.com/watch?v=0uwMKktzixU)
90 | - JavaRush: [Основы Maven](https://javarush.ru/groups/posts/2523-chastjh-4osnovih-maven)
91 | - Инструмент сборки проектов [Maven](https://www.examclouds.com/ru/java/java-core-russian/lesson20)
92 | - [Maven Getting Started Guide](https://maven.apache.org/guides/getting-started/index.html)
93 | - [Видео: Maven vs Gradle vs SBT (Архипов, Борисов, Садогурский)](https://www.youtube.com/watch?v=21qdRgFsTy0)
94 | - [Build Lifecycle](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html)
95 | - [Dependency Mechanism](http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html)
96 |
97 | ##  8. [Как правильно относиться к техзаданию (ТЗ). Полуоткрытый интервал.](https://drive.google.com/file/d/1BpTzjNFjS0TSekCyt_xvt6YoLvuw5KTZ)
98 | - [Типы промежутков](https://ru.wikipedia.org/wiki/Промежуток_(математика))
99 |
100 | ##  Домашнее задание HW0
101 |
102 | ### ВНИМАНИЕ: НЕ НАДО в репозиторий делать Pull Request со своими решениями! См. видео выше ("Работа с проектом")
103 |
104 | Реализовать метод `UserMealsUtil.filteredByCycles` через циклы (`forEach`):
105 | - должны возвращаться только записи между `startTime` и `endTime`
106 | - поле `UserMealWithExcess.excess` должно показывать, превышает ли сумма калорий за весь день значение `caloriesPerDay`
107 |
108 | Т. е. `UserMealWithExcess` - это запись одной еды, но поле `excess` будет одинаково для всех записей за этот день.
109 |
110 | > - Проверьте результат выполнения ДЗ (можно проверить логику в [http://javaops-demo.ru/topjava](http://javaops-demo.ru/topjava), список еды)
111 | > - Оцените Time complexity алгоритма. Если она больше O(N), например O(N*N) или N*log(N), сделайте O(N).
112 | > **Внимание: внимательно прочитайте про O(N). O - это любой коэффициент, 2*N это тоже O(N).**
113 |
114 | - Java 8 Date and Time API
115 | - Алгоритмы и структуры данных для начинающих: сложность алгоритмов
116 | - [Сложность алгоритмов и Big O Notation](https://threadreaderapp.com/thread/1470666237286010881)
117 | - [Головач: сложность алгоритмов в теме коллекций](https://www.youtube.com/watch?v=Ek9ijOiplNE&feature=youtu.be&t=778)
118 | - Time complexity
119 | - Временная сложность алгоритма
120 | - Вычислительная сложность
121 |
122 | #### ВНИМАНИЕ: варианты Optional делайте в одной ветке в разных методах `UserMealsUtil`. Проще делать, проще проверять
123 |
124 | ### Optional (Java 8 Stream API)
125 | ```
126 | Реализовать метод `UserMealsUtil.filteredByStreams` через Java 8 Stream API.
127 | ```
128 | - Видео: Доступно о Java 8 Lambda
129 | - Java 8: Lambda выражения
130 | - Java 8: Потоки
131 | - Pуководство по Java 8 Stream
132 | - [Полное руководство по Java 8 Stream API в картинках и примерах](https://annimon.com/article/2778)
133 | - [7 способов использовать groupingBy в Stream API](https://habrahabr.ru/post/348536)
134 | - Лямбда-выражения в Java 8
135 | - A Guide to Java 8
136 | - Шпаргалка Java Stream API
137 | - Алексей Владыкин: Элементы функционального программирования в Java
138 | - Yakov Fain о новом в Java 8
139 | - stream.map vs forEach`
147 | - без циклов по другим коллекциям/массивам (к ним также относим методы коллекций `addAll()/removeAll()`)
148 | - через Stream API за 1 проход по исходному списку `meals.stream()`
149 | - нельзя использовать внешние коллекции, не являющиеся частью коллектора
150 | - возможно дополнительные проходы по частям списка, при этом превышение должно считаться один раз для всего подсписка. Те например нельзя разбить список на на 2 подсписка с четными и нечетными датами и затем их объединить, с подсчетом превышения для каждого элемента.
151 |
152 | Временная сложность реализации должна быть O(N) (обратите внимание на п. 13 замечаний)
153 | Решение должно быть рабочим в общем случае (должно работать в приложении с многими пользователями, не только при запуске `main`)
154 | Нельзя 2 раза проходить по исходному списку (в том числе по его отфильтрованной или преобразованной копии)
155 |
156 | Ресурсы:
157 | - [Baeldung: Custom Collectors](https://www.baeldung.com/java-8-collectors#Custom)
158 | - [Руководство по Java 8 Stream API: Collector](https://annimon.com/article/2778#collector)
159 | - [Хватит писать циклы! Топ-10 лучших методов для работы с коллекциями из Java 8](https://javarush.ru/groups/posts/524-khvatit-pisatjh-ciklih-top-10-luchshikh-metodov-dlja-rabotih-s-kollekcijami-iz-java8)
160 | - [Понять Java Stream API](https://vc.ru/u/604567-yerlan-akzhanov/194409-ponyat-java-stream-api)
161 |
162 | ### Замечания по использованию Stream API:
163 | - Когда встречаешь что-то непривычное, приходится перестраивать мозги. Например, переход с процедурного на ООП-программирование дается непросто. Те, кто не знает шаблонов (и не хотят учить), также их встречают плохо. Хорошая новость в том, что если это принять и начать использовать, то начинаешь получать от этого удовольствие. И тут главное не впасть в другую крайность:
164 | - [Используйте Stream API проще (или не используйте вообще)](https://habrahabr.ru/post/337350/)
165 | - Если вас беспокоит производительность стримов, обязательно прочитайте про оптимизацию
166 | - ["Что? Где? Когда?"](http://optimization.guide/intro.html)
167 | - [Перформанс: что в имени тебе моём?](https://habrahabr.ru/company/jugru/blog/338732/)
168 | - [Performance это праздник](https://habrahabr.ru/post/326242/)
169 |
170 | При использовании Stream API производительность улучшится только на больших задачах, где возможно распараллеливание.
171 | Еще: просто так запустить и померить скорость JVM нельзя (как минимум надо дать прогреться и запустить очень большое число раз). Лучше использовать какие-нибудь бенчмарки, например [JMH](http://tutorials.jenkov.com/java-performance/jmh.html), который мы используем на другом проекте (Mastejava).
172 |
173 | ##  Замечания к HW0
174 | - 1: Код проекта менять можно! Одна из распространенных ошибок как в тестовых заданиях на собеседовании, так и при работе на проекте, что ничего нельзя менять. Конечно, при правках в рабочем проекте обязательно нужно проконсультироваться/проревьюироваться у авторов кода (находятся по истории VCS)
175 | - 2: Наследовать `UserMealWithExcess` от `UserMeal` нельзя, т. к. это разные сущности: Transfer Object и Entity. Мы будем их проходить на 2-м уроке. Это относится и к их зависимости друг от друга.
176 | - 3: Правильная реализация должна быть простой и красивой, можно сделать 2-мя способами: через стримы и через циклы. Сложность должна быть O(N), т. е. без вложенных стримов и циклов.
177 | - 4: При реализации через циклы посмотрите в `Map` на методы `getOrDefault` или `merge`
178 | - 5: **При реализации через `Stream` заменяйте `forEach` оператором `stream.map(..)`**
179 | - 6: Объявляйте переменные непосредственно перед использованием (если возможно - сразу с инициализацией). При объявлении коллекций в качестве типа переменной используйте интерфейс (Map, List, ..)
180 | - 7: Если IDEA предлагает оптимизацию (желтым подчеркивает), например, заменить лямбду на ссылку на метод (method reference), соглашайтесь (Alt+Enter)
181 | - 8: Пользуйтесь форматированием кода в IDEA: `Alt+Ctrl+L`
182 | - 9: Перед check-in (отправкой изменений на GitHub) просматривайте внесенные изменения (Git -> [Log](https://www.jetbrains.com/help/idea/log-tab.html) -> курсор на файл и Ctrl+D): не оставляйте в коде ничего лишнего (закомментированный код, TODO и пр.). Если файл не меняется (например только пробелы или переводы строк), не надо его чекинить, делайте ему `revert` (Git -> Revert / `Ctrl+Alt+Z`).
183 | - 10: `System.out.println` нельзя использовать нигде, кроме как в `main`. Позже введем логирование.
184 | - 11: Результаты, возвращаемые `UserMealsUtil.filteredByStreams`, мы будем использовать [в нашем приложении](http://javaops-demo.ru/topjava) для фильтрации по времени и отображения еды правильным цветом.
185 | - 12: Обращайте внимание на комментарии к вашим коммитам в Git. Они должны быть короткие и информативные (лучше на english)
186 | - 13: Не полагайтесь в решении на то, что список еды будет подаваться отсортированным. Такого условия нет.
187 | -----
188 |
189 | > - ДЗ первого урока будет связано с созданием небольшого [CRUD](https://ru.wikipedia.org/wiki/CRUD)-приложения (в памяти, без базы данных) на JSP и сервлетах
190 | > - основы JavaScript необходимы для понимания проекта, начиная с 8-го занятия
191 |
192 | ### Полезные ресурсы
193 | #### HTML, JavaScript, CSS
194 | - [Basic HTML and HTML5](https://learn.freecodecamp.org/responsive-web-design/basic-html-and-html5/say-hello-to-html-elements/)
195 | - [Справочник по WEB](https://developer.mozilla.org/ru/)
196 | - [Видео по WEB-технологиям](https://www.youtube.com/user/WebMagistersRu/playlists)
197 | - [Изучение JavaScript в одном видеоуроке за час](https://www.youtube.com/watch?v=QBWWplFkdzw)
198 | - HTML, CSS, JAVASCRIPT, SQL, JQUERY, BOOTSTRAP
199 | - Введение в программирование на JavaScript
200 | - Стандарты кодирования для HTML, CSS и JavaScript’a
201 | - Основы работы с HTML/CSS/JavaScript
202 | - JavaScript - Основы
203 | - Основы JavaScript
204 | - Bootstrap 3 - Основы
205 | - jQuery для начинающих
206 |
207 | #### Java (базовые вещи)
208 | - [Сборник видео "Изучаем Java"](https://www.youtube.com/playlist?list=PLyxk-1FCKqockmP-fXZmHQ7UlYP3qvZRa)
209 | - 1-й урок MasterJava: Многопоточность
210 | - [Основы Java garbage collection](http://web.archive.org/web/20180831013112/https://ggenikus.github.io/blog/2014/05/04/gc)
211 | - Размер Java объектов
212 | - Введение в Java Reflection API
213 | - Структуры данных в картинках
214 | - Обзор java.util.concurrent.*
215 | - Синхронизация потоков
216 | - String literal pool
217 | - Маленькие хитрости Java
218 | - A Guide to Java 8
219 |
220 | ### Туториалы, разное
221 | - [Открытый курс: Spring Boot + HATEOAS](https://javaops.ru/view/bootjava)
222 | - [Что нужно знать о бэкенде новичку в веб-разработке](https://tproger.ru/translations/backend-web-development)
223 | - [Туториалы: Spring Framework, Hibernate, Java Core, JDBC](http://proselyte.net/tutorials/)
224 |
225 | #### Сервлеты
226 | - Как создать Servlet? Полное руководство.
227 | - [Сервлеты](https://metanit.com/java/javaee/4.1.php)
228 |
229 | #### Туториалы по Spring
230 | - [Юрий Ткач: Spring Framework - The Basics](https://www.youtube.com/playlist?list=PL6jg6AGdCNaWF-sUH2QDudBRXo54zuN1t)
231 | - [Java Brains: Spring Framework](https://www.youtube.com/playlist?list=PLC97BDEFDCDD169D7)
232 | - [Тимур Батыршинов: Spring Core - основы фреймворка, ядро](https://www.youtube.com/watch?v=CfHDr-19WWY&list=PL8X2nqRlWfaYYP1-qXjdPKE7bXYkl6aL4)
233 | - [alishev: Spring Framework](https://www.youtube.com/playlist?list=PLAma_mKffTOR5o0WNHnY0mTjKxnCgSXrZ)
234 |
235 | #### JDBC, SQL
236 | - Основы SQL на примере задачи
237 | - Уроки по JDBC
238 | - Learn SQL
239 | - Интуит. Основы SQL
240 | - Try SQL
241 | - Курс "Введение в базы данных"
242 |
243 | #### Разное
244 | - Вопросы по собеседованию, ресурсы для подготовки
245 | - Эффективная работа с кодом в IntelliJ IDEA
246 | - Quizful- тесты онлайн
247 | - Введение в Linux
248 |
249 | #### Книги
250 | - Джошуа Блох: Java. Эффективное программирование. Второе издание
251 | - Гамма, Хелм, Джонсон: Приемы объектно-ориентированного проектирования. Паттерны проектирования
252 | - Редмонд Э.: Семь баз данных за семь недель. Введение в современные базы данных и идеологию NoSQL
253 | - Brian Goetz: Java Concurrency in Practice
254 | - G.L. McDowell: Cracking the Coding Interview
255 |
--------------------------------------------------------------------------------
/ReleaseNotes.md:
--------------------------------------------------------------------------------
1 | # TopJava Release Notes
2 |
3 | ### TopJava 26
4 | - починили шаблоны запросов на создание в Swagger через [ApiModelProperty](https://www.baeldung.com/spring-swagger-hide-field)
5 | - в новой версии Data JPA `getById`->`getReferenceById`
6 | - мелкие правки
7 |
8 | ### TopJava 25
9 | - поправил `NoHtmlValidator`: `Jsoup.clean().equals` -> `Jsoup.isValid`
10 | - починил `role VARCHAR NOT NULL`
11 | - добавил нового тестового пользователя `guest`
12 |
13 | ### TopJava 24
14 | - migrate to LTS JDK 17
15 | - add `AbstractBaseEntity.id()`
16 | - fix for `User.registered`: `@Column(..., updatable = false)`
17 | - add `@QueryHints` in `CrudUserRepository`
18 | - add loggin in `RootController`
19 | - fix `@Sql(.., , executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)` for controller tests after service tests
20 | - rename `MATCHER` to `USER_MATCHER/MEAL_MATCHER`
21 | - treat in `ActiveDbProfileResolver` attribute `profiles`
22 |
23 | ### TopJava 23
24 | - migrate to JDK 16
25 | - в новой spring-data-jpa `getOne` заменили на `getById`
26 | - в UserUtil#prepareToSave убрал проверку пароля на `hasText`. На UI поле проверяется на `@NotBlank`
27 | - `ProfileRestController#register` делаю по правилам REST (POST без "/register")
28 | - css стили `data-...` сделал [low-case через дефисы](https://stackoverflow.com/questions/36176474/548473)
29 | - `TestMatcher` переименовал в `MatcherFactory`
30 | - Для Swagger UI пометил `AuthorizedUser` аннотацией `@ApiIgnore`
31 |
32 | ### TopJava 22
33 | - очистка пароля `AuthorizedUser#userTo`
34 | - заменил `@SafeHtml`, который удалили из `hibernate.validator` на [Jsoup.clean](https://stackoverflow.com/a/68888601/548473)
35 | - перенес запрет на обновление admin/user в `UserService`
36 | - проверку email на уникальность для update с `id=null` в теле запроса сделал на основе анализа `HttpServletRequest.getRequestURI()`
37 | - проверку класса в `classpath` в `Profiles#getActiveDbProfile` делаю на `org.springframework.util.ClassUtils#isPresent`
38 | - удалил `type="text/javascript"`
39 |
40 | ### TopJava 21
41 | - **добавили документирование REST API: Swagger**
42 | - мигрировали на JDK 15 и используем текстовые блоки
43 | - Вынес `produces = MediaType.APPLICATION_JSON_VALUE` на уровень контроллеров
44 | - Правильно используем [глабальные переменные в js](https://stackoverflow.com/a/5064235/548473)
45 | - Зарефакторил `inputField.tag`
46 | - Тестовые переменные переименовал из UPPERCASE в camelCase
47 | - Из тестов сервисов убрал `throws Exception` (в IDEA больше не генерятся по умолчанию)
48 | - **Мигрировали на Spring Boot 2.4.1**
49 |
50 | ### TopJava 20
51 | - мигрировали на JDK 14
52 | - в `@SafeHtml` запрещаем весь html (`whitelistType = NONE`)
53 | - в `topjava.common.js` в `makeEditable()` вместо объекта контекст передаю 3 параметра
54 | - в UI контроллерах убрал префикс `ajax`
55 | - из тестов сервисов убрал `repository`. При проверке через `assertThrows` он не требуется
56 | - в `TestMatcher` сценарии сравнения сделал параметризируемыми (паттерн стратегия)
57 | - в API добавили `/users/{id}/with-meals` (см. [двунаправленные отношения](https://www.codeflow.site/ru/article/jackson-bidirectional-relationships-and-infinite-recursion))
58 | - добавил `UserTestData.USER_WITH_MEALS_MATCHER` (проверки пользователя сразу с едой) и константу id `NOT_FOUND`
59 |
60 | ### TopJava 19
61 | - Изменилась логика для интервалов времени (исключаем `endTime`)
62 | - Заменил собственный `MessageUtil` велосипед на спринговый `MessageSourceAccessor`
63 | - В ролях убрал префиксы `ROLE_` ([Role and GrantedAuthority](https://stackoverflow.com/a/19542316/548473))
64 | - Добавился удобный метод `int AbstractBaseEntity.id()`
65 | - Фикс `Location` в `ProfileRestController.register`
66 | - Фикс валидации `UniqueMailValidator` для REST update без `user.id`
67 | - Заменил `jdbc.initLocation` на полный путь - IDEA не ругается
68 | - В конфигурации `cargo-maven2-plugin` сделал [индивидуальный контекст приложения](https://stackoverflow.com/a/60797999/548473)
69 | - Тесты
70 | - Обновил даты еды на 2020г.
71 | - Зарефакторил тесты сервисов на удаление - `NotFoundException` может бросаться при `delete()`
72 | - В тестах контроллеров вернулся к реализации без обертки над `MockMvcRequestBuilders`
73 | - Для `InMemory` тестов подключаю только `inmemory.xml` (добавил туда необходимую конфигурацию из `spring-app.xml`)
74 |
75 |
76 | ### TopJava 18
77 |
78 | - В `ErrorType` добавил `HttpStatus status`
79 | - В PostgreSQL обнаружилась бага: граничное значение `0:00` из-за ошибок округления попадает в предыдущий интервал.
80 | Мораль: всегда в тестах проверяйте граничные значения. Добавил этот случай в тестовые данные.
81 | - Изменил `MealRepository.getBetween` (принимаю `@Nullable LocalDate`). Изменились реализации.
82 | - Выделил метод `UserService.prepareAndSave`
83 | - В TO поля сделал `final`, используем `@ConstructorProperties`
84 | - Наконец локализировал описание приложения на страничке входа
85 | - Для полей ввода дат добавил `autocomplete="off"`
86 | - При закрытии модального окна закрываю окно ошибок
87 | - Тесты:
88 | - **Вместо очистки кэшей перед каждым тестом отключаем кэши для всех тестов**
89 | - **Вынес общий код тестирования контроллеров в `AbstractControllerTest`. Код тестов значительно сократился**
90 | - **Сделал типизированный `TestMatchers` для проверки результатов тестов. В классах `UserTestData` и `MealTestData` создаю его инстансы с заданным типом и методикой сравнения.**
91 | - В тестах `delete` и `create` проверяю результат напрямую (не через `getAll`)
92 |
93 |
94 | ### TopJava 17
95 | - Удалил `Impl` из названий репозиториев
96 | - Удалил интерфейсы к сервисам, использую классы
97 | - Добавил `AdminRestController.enable`, вызов через PATCH метод
98 | - Добавил валидацию для jdbc через Bean Validation API
99 | - Перенес работу в UI с профилем из `RootController` в `ProfileUIController`
100 | - `SLF4JBridgeHandler` инициализирую только в профиле `postgres`
101 |
102 | ### TopJava 16
103 | - Выделил общий код реализации хранения в памяти в `InMemoryBaseRepositoryImpl`
104 | - Сделал подтверждение для удаления записей
105 | - Обновились видео 7-го занятия. [Выложил его как пример занятия, некоторые видео открыты](https://github.com/JavaOPs/topjava/blob/master/doc/lesson07.md)
106 | - Сделали валидации дублирования email через `WebDataBinder` и `Validator`
107 |
108 | ### TopJava 15
109 | - Миграция на Servlet API 4.0 / Tomcat 9.x
110 | - [Миграция на JDK11](http://javaops.ru/view/resources/jdk8_11)
111 | - JUnit5 fix: junit-platform-surefire-provider не нужен
112 | - Рефакторинг тестов:
113 | - в `RootControllerTest.testUsers` для проверки используем `AssertionMatcher` адаптер
114 | - вместо `content().json()` от `jsonassert` десериализуем json и используем сравнения через `AssertJ`
115 | - В javascript место глабальных переменных и одинаковой функции обновления таблицы задаю их в объекте контекст, который передаю в `makeEditable()` как параметр
116 | - Починил `back` в браузере после логина. Кнопки входа и регистрации отображаю только для `isAnonymous()`
117 |
118 | ### TopJava 14
119 | - [Миграция на JUnit 5](http://javaops.ru/view/resources/junit5)
120 | - Для измерения времени в тестах использую [Spring StopWatch](https://www.logicbig.com/how-to/code-snippets/jcode-spring-framework-stopwatch.html)
121 | - `SimpleJdbcInsert` и `NamedParameterJdbcTemplate` конструируются (и берут настройки) из `jdbcTemplate`
122 | - `AuthorizedUser` зарефакторился в `SecurityUtil`
123 | - В javascript [заменил `var` на `let/const`](https://learn.javascript.ru/let-const). [Поддержка 95% браузеров](https://caniuse.com/#feat=const)
124 | - Подправил UI фильтрации и заголовка страниц, добавилась кнопка `Cancel` в профиль
125 | - Починил [баг в FireFox](https://bugzilla.mozilla.org/show_bug.cgi?id=884693): пустой ответ по ajax
126 | - Сделал вход в приложение при нажании кнопок `Зайти как ...`
127 | - Добавил регистрацию пользователя по REST
128 | - Преименовал js файлы согласно [javascript filename naming convention](https://stackoverflow.com/questions/7273316/what-is-the-javascript-filename-naming-convention)
129 | - Сделал проверку startTime/endTime на фильтре времени (после обновления datetimepicker до 2.5.20)
130 |
131 | ### TopJava 13
132 | - [Миграция на Botstrap 4](https://getbootstrap.com/docs/4.1/migration/)
133 | - Добавил [Responsive behaviors](https://getbootstrap.com/docs/4.1/components/navbar/#responsive-behaviors) - при уменшении ширины экрана навигация сворачивается в кнопку
134 | - Для отображения цвета еды и выключенного юзера использую [data-* атрибуты](https://developer.mozilla.org/ru/docs/Web/Guide/HTML/Using_data_attributes)
135 | - В `inputField.tag` передаю как параметр код для локализации label, а в `i18n.jsp` передаю как параметр `page`. См. [JSP include action with parameter example](https://beginnersbook.com/2013/12/jsp-include-with-parameter-example)
136 |
137 | ### TopJava 12
138 | - [Миграция на Spring 5](http://javaops.ru/view/resources/spring5)
139 | - обновил версии: Ehcache 3.x, datatables, datetimepicker
140 | - добавил видео решений HW0 с одним проходом
141 | - поправил видео [Обзор Spring Framework. Spring Context](https://drive.google.com/file/d/1fBSLGEbc7YXBbmr_EwEHltCWNW_pUmIH). Дописал про Constructor injection.
142 | - заменил видео про тетсирование сервисов. Вместо самодельных матчеров стали использовать [AssertJ](http://joel-costigliola.github.io/assertj/index.html). Видео [Тестирование UserService через AssertJ](https://drive.google.com/open?id=1SPMkWMYPvpk9i0TA7ioa-9Sn1EGBtClD), время 1:53
143 | - сделал [видео с jQuery конвертерами и дефолтными группами валидации при сохранении в базу](https://drive.google.com/open?id=1tOMOdmaP5OQ7iynwC77bdXSs-13Ommax)
144 | - сделал [видео с новым `DelegatingPasswordEncoder` и Json READ/WRITE access](https://drive.google.com/file/d/1XZXvOThinzPw4EhigAUdo8-MWT_g8wOt/view?usp=sharing)
145 | - убрал `AccessType.PROPERTY` для `AbstractBaseEntity.id` (см. [fixed HHH-3718](https://hibernate.atlassian.net/browse/HHH-3718))
146 | - удалил `PasswordUtil`, возвращаю статус `NO_CONTENT` для REST delete, убрал группы валидации в `UserTo`
147 | - заменил в jQuery [success на done](https://stackoverflow.com/a/22213543/548473)
148 | - вместо `lang.jsp` сделал общий `bodyHeader.jsp`
149 |
150 | ### TopJava 11
151 | - добавил
152 | - доп. решение HW1 через одним return и O(N)
153 | - раскрасил лог ([Logback layouts coloring](https://logback.qos.ch/manual/layouts.html#coloring))
154 | - рефакторинг
155 | - починил коммит формы по cancel (`history.back()`) в FireFox
156 | - заменил неработающий DependencyCi на [VersionEye](https://www.versioneye.com/) c проверкой зависимостей на uptodate
157 | - починил `CrudUserRepository.getWithMeals()` через `@EntityGraph`. С неколькими ролями (у админа) еда дублируется
158 | - починил тесты контроллеров с профилем JDBC (`JpaUtil` отсутствует в контексте JDBC)
159 | - переименовал `meal.jsp/user.jsp` в `mealForm.jsp/userForm.jsp`
160 | - в `InMemoryMealRepositoryImpl.save()` сделал update атомарным
161 | - переименовал методы сервисов `save` в `create`
162 | - переименовал и cделал классы `BaseEntity` и `NamedEntity` абстрактными
163 | - обновил Noty и API с ним до 3.1.0. Добавил glyphicon в сообщения Noty
164 | - заменил `MATCHER_WITH_EXCEED` на валидацию через [JSONassert](https://github.com/skyscreamer/JSONassert).
165 | - поменял Deprecated валидаторы `org.hibernate.validator.constraints` на `javax.validation.constraints`
166 | - убрал пароль из результатов REST через [@JsonProperty READ_ONLY / WRITE_ONLY](https://stackoverflow.com/questions/12505141/only-using-jsonignore-during-serialization-but-not-deserialization/12505165#12505165). Тесты на REST пришлось починить добавлением добавлением в JSON пароля как дополнительного параметра (`JsonUtil.writeWithExtraProps`)
167 | - **убрал JSON View и сделал преобразование времени на UI с помощью [jQuery converters](http://api.jquery.com/jQuery.ajax/#using-converters)**
168 | - **поменял [группу валидации по умолчанию при сохранении через JPA](https://stackoverflow.com/questions/16930623/16930663#16930663).** Теперь
169 | все валидаторы в модели работаю по умолчанию (`groups` не требуется).
170 | - Добавил в `ErrorInfo` тип ошибки `ErrorType` + i18n.
171 |
172 | - правки
173 | - переименовал `ModelMatcher` в `BeanMatcher` и починил: можно сравнивать только упорядоченные коллекции (List)
174 | - поменял зависимость `org.hibernate:hibernate-validator` на `org.hibernate.validator:hibernate-validator` (warning при сборке)
175 |
176 | ### TopJava 10
177 | - добавил
178 | - доступ к AuthorizedUser через [`@AuthenticationPrincipal`](http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#mvc-authentication-principal) и [authentication Tag](http://docs.spring.io/spring-security/site/docs/current/reference/html/taglibs.html#the-authentication-tag)
179 | - [Обработку 404 NotFound](https://stackoverflow.com/questions/18322279/spring-mvc-spring-security-and-error-handling)
180 | - локализацию ошибок валидации
181 | - проверки json в тестах через [JSONassert](https://github.com/skyscreamer/JSONassert) и [через jsonPath](https://www.petrikainulainen.net/programming/spring-framework/integration-testing-of-spring-mvc-applications-write-clean-assertions-with-jsonpath/)
182 | - [логирование от Postgres Driver](http://stackoverflow.com/a/43242620/548473)
183 | - в `.travis.yml` [сборку только ветки master](https://docs.travis-ci.com/user/customizing-the-build#Building-Specific-Branches)
184 | - [защиту от кэширование ajax запросов в IE](https://stackoverflow.com/a/4303862/548473)
185 | - обработку запрета модификации системный юзеров через универсальный `ApplicationException`
186 | - рефакторинг
187 | - сделал `@EntityGraph` через `attributePaths`
188 | - реализаовал обработку дублирования `user.email` и `meal.dateTime` через [Controller Based Exception Handling](https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc#controller-based-exception-handling)
189 | - поменял отключение транзакционности в тестах через `@Transactional(propagation = Propagation.NEVER)`
190 | - сделал выбор в сервлете через switch
191 | - [все логгирование сделал через {} форматирование](http://stackoverflow.com/questions/10555409/logger-slf4j-advantages-of-formatting-with-instead-of-string-concatenation) и поправил его в контроллерах (поле проверки id)
192 | - [перешел на конструктор DI](http://stackoverflow.com/questions/39890849/what-exactly-is-field-injection-and-how-to-avoid-it)
193 | - в `ModelMatcher` переименовал `Comparator` -> `Equality`
194 | - [заинлайнил все лямбды](http://stackoverflow.com/questions/19718353/is-repeatedly-instantiating-an-anonymous-class-wasteful) (компараторы, ModelMatcher.equality)
195 | - поменялась реализация `JdbcUserRepositoryImpl.getAll()`
196 | - на UI кнопки в таблице заменились на линки, поправил сообщения локализации
197 | - [сделал кастомизацию JSON (@JsonView) и валидацию (groups)](https://drive.google.com/file/d/0B9Ye2auQ_NsFRTFsTjVHR2dXczA) для данных еды, отдаваемых на UI
198 | - в `JdbcUserRepositoryImpl` поменял `MapSqlParameterSource` на `BeanPropertySqlParameterSource`
199 | - удалил
200 | - зависимость `javax.transaction.jta` (уже не нужна)
201 | - `${spring.version}` в `pom.xml` зависимостях (уже есть в `spring-framework-bom`)
202 | - distinct из запроса Hibernate на пользователей с ролями. [Оптимизация запроса distinct: 15.16.2](https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#hql-distinct)
203 | - лишние `
` тэги (`shadow` и `view-box`)
204 |
205 | ### TopJava 9
206 | - добавил
207 | - выбор профиля базы через `ActiveProfilesResolver`/`AllActiveProfileResolver` на основе драйвера базы в classpath
208 | - видео Cascade. Auto generate DDL.
209 | - проверку на правильность id в Ajax/Rest контроллерах (treat IDs in REST body)
210 | - тесты на валидацию входных значений контроллеров и зависимость на имплементацию
211 | - Bootstrap Glyphicons
212 | - рефакторинг
213 | - переименовал `TimeUtil` в `DateTimeUtil`
214 | - переименовал `ExceptionUtil` в `ValidationUtil`
215 | - заменил валидацию `@NotEmpty` на `@NotBlank`
216 | - заменил `CascadeType.REMOVE` на `@OnDelete`
217 | - изменил `JdbcUserRepositoryImpl.getAll()`
218 | - обновил jQuery до 3.x, исключил из зависимостей webjars ненужные jQuery
219 | - cделал загрузку скриптов асинхронной
220 | - фильтр еды сделал в [Bootstrap Panels](http://getbootstrap.com/components/#panels)
221 | - вместо `Persistable` ввел интерфейс `HasId` и наследую от него как Entity, так и TO
222 | - сделал универсальную обработку исключений дублирования email и dateTime
223 |
224 | ### TopJava 8
225 | - добавил:
226 | - [защиту от XSS (Cross-Site Scripting)](http://stackoverflow.com/a/40644276/548473)
227 | - интеграцию с Dependency Ci и Travis Ci
228 | - локализацию календаря
229 | - сводку по результатам тестов
230 | - примеры запросов curl в `config/curl.md`
231 | - DataTables/Bootstrap 3 integration
232 | - тесты на профиль деплоя Heroku (общее количество JUnit тестов стало 102)
233 | - удалил зависимость `jul-to-slf4j`
234 | - рефакторинг
235 | - переименовал все классы `UserMeal**` в `Meal**`, JSP
236 | - переименовал `LoggedUser` в `AuthorizedUser`
237 | - починил работа с PK Hibernate в случае ленивой загрузки (баг HHH-3718)
238 | - поменял в `BaseEntity` `equals/hashCode/implements Persistable`
239 | - в `InMemoryMealRepositoryImpl` выделил метод `getAllStream`
240 | - перенес проверки пердусловий `Assert` из `InMemory` репозиториев в сервисы
241 | - переименовал классы _Proxy*_ на более адекватные _Crud*_
242 | - поменял реализацию `JpaMealRepositoryImpl.get`, добавил в JPA модель `@BatchSize`
243 | - вместо `@RequestMapping` ввел Spring 4.3 аннотации `@Get/Post/...Mapping`
244 | - поменял авторизацию в тестах не-REST контроллеров
245 | - перенес вызовы `UserUtil.prepareToSave` из `AbstractUserController` в `UserServiceImpl`
246 | - зарефакторил обработку ошибок (`ExceptionInfoHandler`)
247 |
248 | ### TopJava 7
249 | - добавил:
250 | - [JPA 2.1 EntityGraph](https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs002.htm)
251 | - [Jackson @JsonView](https://habrahabr.ru/post/307392/)
252 | - валидацию объектов REST
253 | - [i18n в JavaScript](http://stackoverflow.com/a/6242840/548473)
254 | - проверку предусловий и видео Методы улучшения качества кода
255 | - интеграцию с проверкой кода в Codacy
256 | - [сравнение вермени исполнения запросов при различных meals индексах](https://drive.google.com/open?id=0B9Ye2auQ_NsFX3RLcnJCWmQ2Y0U)
257 | - tomcat7-maven-plugin плагин перключили на Tomcat 8 (cargo-maven2-plugin)
258 | - рефакторинг
259 | - обработка ошибок сделал с array
260 | - матчеров тестирования (сделал автоматические обертки и сравнение на основе передаваемого компаратора)
261 | - вынес форматирование даты в `functions.tld`
262 |
263 | ### TopJava 3-6
264 | - добавил
265 | - [выпускной проект](https://drive.google.com/open?id=0B9Ye2auQ_NsFcG83dEVDVTVMamc)
266 | - в таблицу meals составной индекс
267 | - константы `Profiles.ACTIVE_DB`, `Profiles.DB_IMPLEMENTATION`
268 | - проверки и тесты на `NotFound` для `UserMealService.getWithUser` и `UserService.getWithMeals`
269 | - в MockMvc фильтр CharacterEncodingFilter
270 | - защиту от межсайтовой подделки запроса, видео Межсайтовая подделка запроса (CSRF)
271 | - ограничение на диапазон дат для фильтра еды
272 | - рефакторинг
273 | - UserMealsUtil, ProfileRestController, компараторов в репозитоии
274 | - `LoggedUser` отнаследовал от `org.springframework.security.core.userdetails.User`
275 | - переименовал `DbTest` в `AbstractServiceTest` и перенес сюда `@ActiveProfiles`
276 | - сделал выполнение скриптов в тестах через аннотацию `@Sql`
277 | - вместо использования id и селектора сделал обработчик `onclick`
278 | - изменил формат ввода даты в форме без 'T'
279 | - убрал
280 | - `LoggerWrapper`
281 | - Dandelion обертку к datatables
282 | - обновил
283 | - Hibernate до 5.x и Hibernate Validator, добавились новые зависимости и `jackson-datatype-hibernate5`
284 | - datatables API (1.10)
285 | - Postgres драйвер. Новый драйвер поддерживает Java 8 Time API, разделил реализацию JdbcMealRepositoryImpl на Java8 (Postgresql) и Timestamp (HSQL)
286 |
--------------------------------------------------------------------------------
/cv.md:
--------------------------------------------------------------------------------
1 | ## Составление резюме, подготовка к интервью, поиск работы
2 |
3 | 
4 |
5 | - Научиться программировать сложнее, чем кажется
6 | - [Собеседование. Разработка ПО. Вопросы.](https://drive.google.com/file/d/0B9Ye2auQ_NsFQVc2WUdCR0xvLWM/view?usp=sharing&resourcekey=0-HaWoRxoyboMSKjg5P2I1cQ)
7 | - [Набор ссылок для тренировки и прохождения интервью](https://github.com/andreis/interview)
8 | - [Полезные советы Jun-ам](https://github.com/JavaOPs)
9 |
10 | ### Составление резюме:
11 | - [VisualCV: create resume in minutes](https://www.visualcv.com/)
12 | - Выбрать шаблон для резюме
13 | - [GitHub Pages](https://pages.github.com/), Resume template
14 | - Как продать свое резюме в 2 раза дороже
15 | - Как правильно составить резюме
16 | - Резюме программистов. Часть 1 (плохие)
17 | - Резюме программистов. Часть 2 (хорошие)
18 | - Как составить резюме на английском
19 | - ОФОРМЛЕНИЕ IT-РЕЗЮМЕ для USA
20 |
21 | ### Наши истории (делимся опытом и успехом)
22 |
23 | ### Тесты/задачи онлайн:
24 | - [Interviewing: the most profitable skill you can learn (pramp.com)](https://www.pramp.com/)
25 | - [Java Programming Test](https://tests4geeks.com/java)
26 | - game: test Java skills
27 | - Codility lesson tests
28 | - Quizful- тесты онлайн
29 | - LeetCode Online Judge
30 | - Sphere online judge
31 | - Codility programmers lessons
32 | - Hackerrank practice coding
33 | - [start.interviewing.io](https://start.interviewing.io/)
34 |
35 | ## [Тестовое собеседование, самые спрашиваемые темы](http://javaops.ru/interview/test.html)
36 |
37 | ### Интервью:
38 | - [Собеседования для бэкендеров: как готовиться, тренироваться и не облажаться](https://habr.com/ru/companies/getmatch/articles/744760/)
39 | - [10 неочевидных фактов об ИТ-собеседованиях](https://proglib.io/p/molchanie-intervyuera-ili-10-neochevidnyh-faktov-ob-it-sobesedovaniyah-2022-06-14)
40 | - Михаил Портнов. Собеседование на работу: как продать себя грамотно
41 | - Михаил Портнов. Какие вопросы мы задаем на собеседовании?
42 | - Михаил Портнов. Собеседование на работу: жизненный путь
43 | - [Лёша Корепанов. Признаки плохих компаний для программиста](https://www.youtube.com/watch?v=Sj-WSWr-n7U)
44 | - [Лёша Корепанов. Как отвечать на вопросы, которые ты не знаешь. Техническое интервью для программиста](https://www.youtube.com/watch?v=Beoh3tfgPEk)
45 | - Канал: Резюме, поиск работы, интервью
46 | - Яков Файн: Как стать профессиональным Java разработчиком
47 | - Ответы на вопросы на собеседовании Junior Java Developer
48 | - Список вопросов с ответами для собеседования по Java
49 | - Сборка по вопросам на интервью
50 | - Сборка вопросов-ответов от JavaStudy
51 | - [Видео технических интервью от Максима Добрынина](https://www.youtube.com/playlist?list=PLxqzxxW1gWwJvVK11R_lJKAlP_9m3Gu2H)
52 | - [Вопросы по классам коллекциям от JavaRush-1](http://info.javarush.ru/translation/2013/10/08/Часто-задаваемые-на-собеседованиях-вопросы-по-классам-коллекциям-в-Java-Часть-1-.html)
53 | - [Вопросы по классам коллекциям от JavaRush-2](http://info.javarush.ru/translation/2013/10/08/Часто-задаваемые-на-собеседованиях-вопросы-по-классам-коллекциям-в-Java-Часть-2-.html)
54 | - Тест на знание SQL
55 | - Вопросы на собеседовании Java Junior Developer
56 | - Java вопросы с собеседований на Android
57 | - Сборка вопросов от JavaRush
58 | > про clone и finalize объязательно прочтите Джошуа Блох: Java. Эффективное программирование (второе издание)
59 |
60 | - Cracking the Coding Interview
61 | > Особенно обратите внимание на раздел: Часть VIII. Вопросы собеседования
62 |
63 |
64 | ### От себя:
65 | - email, skype - очень желательно, чтобы по ним вы были узнаваемы. Заведите рабочие, если не так.
66 | - написать ВЕСЬ IT опыт (исключая опыт пользователя: Windows, MS Word, Photophop, Yandex disk, Google docs, ..): технологии, какие задачи решали (конкретные), какие инструменты использовали, VCS, DB, инструменты сборки, ... включая опыт в ВУЗе.
67 | - на English иметь желательно. Если вакансия опублинована на Englsih - шлите на нем. Часто могут на нем попросить, если работодатель иностранный.
68 | - удобно иметь резюме где-то в Интернете (hh, linkedin, google doc, чтобы им было удобно делиться).
69 |
70 | ### Позиционирование проекта TopJava:
71 | - Обязательно убери из резюме **любое упоминание Junior**. Количество обращений возрастет на порядок. Ссылку на стажировку можно поставить: http://javaops.ru/view/topjava (в linkedin: https://www.linkedin.com/company/java-online-projects).
72 | - После завершения проекта ты освоишь все заявленные в нем технологии - вставь их в квалификацию (включая Java 8 Stream and Time API).
73 | - В разделе опыт работы (если нет коммерческого опыта) вставь:
74 |
75 | Участие в разработке Spring/JPA Enterprise приложения c авторизацией и правами доступа на основе ролей
76 | на стеке Maven/ Spring MVC/ Security/ REST(Jackson)/ Java 8 Stream API:
77 | - реализация сохранения в базы Postgres и HSQLDB на основе Spring JBDC, JPA(Hibernate) и Spring-Data-JPA
78 | - реализация и тестирование REST и AJAX контроллеров
79 | - реализация клиента на Bootstrap (css/js), DataTables, jQuery + plugins.
80 | - собственная доработка проекта
81 |
82 | - Делай упор не на обучение, а на **участие в проекте**. Выполнение домашних заданий это полноценное участие с написанием функционала по всем пройденным технологиям. На собеседовании смотрят не на то, что ты заканчивал, а на опыт и знания.
83 |
84 | ### В процессе обучения
85 | - Если рассматриваешь предложения по работе, подними в своем профиле этот флаг и обязательно заполни ссылку на резюме. Обновления нашей базы выпускников смотрят уже более 125 партнеров по трудоустройству (компании и индивидуальные рекрутеры). Проверь содержание "Информация для HR": по нему принимают решение, открывать резюме или нет.
86 |
87 | - Вступайте в нашу группу участников Slack: каналы помощи с Java, отзывы о работодателях, обсуждение тестовых заданий, вакансии, цены на рынке труда, IT события, интересные видео и многое другое.
88 |
89 | - Подпишитесь на рассылку вакансий под себя
90 |
91 | ### После прохождения испытательного срока жду твою [историю успеха](http://javaops.ru/view/story)
92 |
93 | ### Основные сайты поиска работы:
94 | - [Актуальная подборка Junior вакансий от CodeReview](https://jobs.yourcodereview.com?utm_source=partner&utm_medium=javaops&utm_campaign=landing)
95 | - Яндекс агрегатор
96 | - HH
97 | - LinkedIn
98 | - ХабрКарьера
99 | - [headz.io](https://app.headz.io/candidates/new)
100 | - djinni.co (более актуально для Украины)
101 |
102 | [Как изучать Java. Подборка от JavaRush](https://javarush.ru/groups/posts/3538-v-zakladki-kak-izuchatjh-java-boljhshaja-podborka-po-planu-obuchenija-instrumentam-i-poiskam-mo)
103 |
Как выжить на испытательном сроке
104 |
105 | - Учись грамотно формулировать проблему. Проблема "у меня не работает" может иметь тысячи причин. В
106 | процессе формулирования очень часто приходит ее решение.
107 | - Учись инвестигировать проблему. Внимательное чтение логов и умение дебажить - основные навыки
108 | разработчика. В логах надо читать верх самого нижнего эксепшена - там причина всей портянки.
109 | - Грамотно уделяй время каждой проблеме. Две крайности: сразу бросаться за помощью и
110 | биться над проблемой часами.
111 | Пробуй решить ее сам и, в зависимости от проблемы, выделяй на это разумное время.
112 | - Не бросайся сразу писать код, поищи в проекте схожий функционал! И далее - минимум своих подходов, если хотите внести что-то свое - обязательно спросите!
113 | Проект должен быть однотипным по максимуму во всех мелочах: - описание, пакеты, имена классов и методов и даже переменных, реализация, хелп.
114 | Обычно можно найти сходный функционал, взять его себе и делать в нем изменения под свою реализацию.
115 | - Если тебе что-то объясняют по проекту - обязательно записывай.
116 | - Когда получаешь задачу - уточни все очень подробно. Если задач несколько - обязательно выясни приоритеты!
117 | - Получай в процессе решения обратную связь - в том ли направлении ты идешь
118 | - Не игнорируй совместные ланчи (курилки)
119 | - Готовься к стендапам/летучкам. Задавай на них вменяемые вопросы. Выказывай заинтересованность
120 | - Выдели самое главное путем опроса босса и важных коллег. Не распыляйся на мелочи.
121 | - [**5 вещей, которые разработчик должен сделать прежде чем попросить о помощи**](https://techrocks.ru/2018/07/16/5-things-a-developer-should-do-before-asking-for-help/)
122 | - [**Советы новичкам**](https://blog.csssr.com/ru/article/how-to-be-a-beginner-developer)
123 | - [ТОП-13 ошибок начинающего программиста](https://proglib.io/p/beginners-fails/)
124 | - [25 ошибок начинающего программиста](https://habr.com/ru/post/413129/)
125 | - [Путеводитель по синдрому самозванца](https://vc.ru/hr/167443-eshche-odin-putevoditel-po-sindromu-samozvanca-korni-prichiny-simptomy-i-posledstviya-chast-1)
126 | - [Нетехнические навыки](https://tproger.ru/experts/softskills-for-job)
127 | - Видео [Junior и испытательный срок на первой работе](https://www.youtube.com/watch?v=GsGlsCbok-c)
128 | - Типичные ошибки начинающих программистов от JavaRush:
129 | - [Часть 1](https://javarush.ru/groups/posts/3044-razbor-tipichnihkh-oshibok-nachinajujshikh-programmistov-chastjh-1)
130 | - [Часть 2](https://javarush.ru/groups/posts/3055-razbor-tipichnihkh-oshibok-nachinajujshikh-programmistov-chastjh-2)
131 | - [От джуна к миддлу: практические советы](https://tproger.ru/articles/ot-dzhuna-k-middlu-prakticheskie-sovety)
132 | ## [Отзывы по стажировке TopJava](https://vk.com/topic-74381644_30447246)
133 |
--------------------------------------------------------------------------------
/description.md:
--------------------------------------------------------------------------------
1 | #### Разработка полнофункционального Spring/JPA Enterprise приложения c авторизацией и правами доступа на основе ролей с использованием наиболее популярных инструментов и технологий Java: Maven, Spring MVC, Security, JPA(Hibernate), REST(Jackson), Bootstrap (css, js), DataTables, jQuery + plugins, Java 8 Stream and Time API и сохранением в базах данных PostgreSQL и HSQLDB.
2 |
3 | - Основное внимание будет уделяться способам решения многочисленных проблем разработки в Spring/JPA, а также структурному (красивому и надежному) java-кодированию и архитектуре приложения.
4 | - Каждая итерация проекта закрепляется домашним заданием по реализации схожей функциональности. Следующее занятие начинается с разбора домашних заданий.
5 | - Большое внимание уделяется тестированию кода: в проекте более 100 JUnit-тестов.
6 | - Несмотря на относительно небольшой размер, приложение разрабатывается с нуля как большой проект: например, используем кэш 2-го уровня Hibernate, настраиваем Jackson для работы с ленивой загрузкой Hibernate, делаем конвертеры для типов LocalDateTime (Java 8 time API).
7 | - Разбираются архитектурные паттерны: слои приложения и как правильно разбивать логику по слоям, когда нужно применять Data Transfer Object. То есть на выходе получается не учебный проект, а хорошо масштабируемый шаблон для большого проекта на всех пройденных технологиях.
8 | - Большое внимание уделяется деталям: популяция базы данных, использование транзакционности, тесты сервисов и REST-контроллеров, настройка EntityManagerFactory, выбор реализации пула коннектов. Особое внимание уделяется работе с базой данных: через Spring JDBC, Spring ORM и Spring Data Jpa.
9 | - Используются самые востребованные на сегодняшний момент фреймворки: Maven, Spring Security 4 вместе с Spring Security Test, наиболее удобный для работы с базой проекта Spring Data Jpa, библиотека логирования Logback, реализующая SLF4J, повсеместно используемый Bootstrap и jQuery.
10 |
11 | #### Демо разрабатываемого приложения
12 |
13 | ## План проекта (ссылки на некоторые темы открыты для просмотра)
14 | ### Архитектура проекта. Персистентность.
15 | - Системы управления версиями
16 | - Java 8: Lambda, Stream API
17 | - Обзор используемых в проекте технологий и инструментов.
18 | - Инструмент сборки Maven
19 | - WAR. Веб-контейнер Tomcat. Сервлеты.
20 | - Логирование.
21 | - Обзор стандартных библиотек. Apache Commons, Guava
22 | - Слои приложения. Создание каркаса приложения.
23 | - Обзор Spring Framework. Spring Context.
24 | - Тестирование через JUnit.
25 | - Spring Test
26 | - Базы данных. PostgreSQL. Обзор NoSQL и Java persistence solution без ORM.
27 | - Настройка Database в IDEA.
28 | - Скрипты инициализации базы. Spring Jdbc Template.
29 | - Spring: инициализация и популирование БД
30 | - ORM. Hibernate. JPA.
31 | - [Тестирование JPA-сервиса через AssertJ](https://www.youtube.com/watch?v=BlyaXT6tOaw)
32 | - Поддержка HSQLDB
33 | - Транзакции
34 | - Профили Maven и Spring
35 | - Пул коннектов
36 | - Spring Data JPA
37 | - Кэш Hibernate
38 |
39 | ### Разработка WEB
40 | - Spring кэш
41 | - Spring Web
42 | - JSP, JSTL, i18n
43 | - Tomcat maven plugin. JNDI
44 | - Spring Web MVC
45 | - Spring Internationalization
46 | - Тестирование Spring MVC
47 | - REST-контроллеры
48 | - Тестирование REST-контроллеров. Jackson.
49 | - jackson-datatype-hibernate. Тестирование через матчеры.
50 | - Тестирование через SoapUi. UTF-8
51 | - WebJars.
52 | - Bootstrap. jQuery datatables.
53 | - AJAX. jQuery. Notifications.
54 | - Spring Security
55 | - Spring Binding/Validation
56 | - Работа с DataTables через Ajax.
57 | - Spring Security Test
58 | - [Кастомизация JSON (@JsonView) и валидации (groups)](https://drive.google.com/file/d/0B9Ye2auQ_NsFRTFsTjVHR2dXczA/view?usp=sharing&resourcekey=0-Ou4A_gRor5HaRho4Fciqdw)
59 | - Encoding password
60 | - CSRF (добавление в проект защиты от межсайтовой подделки запроса)
61 | - form-login. Spring Security Taglib
62 | - Handler interceptor
63 | - Spring Exception Handling
64 | - Смена локали
65 | - Фильтрация JSON с помощью @JsonView
66 | - Защита от XSS (Cross Site Scripting)
67 | - Деплой на [собственный выделенный сервер](https://github.com/JavaOPs/startup)
68 | - Локализация datatables, ошибок валидации
69 | - Обработка ошибок 404 (NotFound)
70 | - Доступ к AuthorizedUser
71 | - Собеседование. Разработка ПО
72 |
73 | ### Миграция на Spring Boot
74 | - Основы Spring Boot. Spring Boot maven plugin
75 | - Lombok, база H2, ApplicationRunner
76 | - Spring Data REST + HATEOAS
77 | - Swagger/ OpenAPI 3.0
78 | - Тестирование и кэширование в Spring Boot
79 | - Миграция приложения TopJava на Spring Boot
80 |
--------------------------------------------------------------------------------
/doc/lesson07.md:
--------------------------------------------------------------------------------
1 | # [Онлайн стажировка Spring 5/JPA Enterprise (TopJava)](http://javaops.ru/view/topjava)
2 | ## [Почему мы?](http://javaops.ru/#why)
3 |
4 | ## REST, REST-контроллеры, тестирование контроллеров Spring MVC
5 | # Для просмотра открыты видео [4](#--4-миграция-на-junit-5), [5](#-5-принципы-rest-rest-контроллеры), [6](#-6-тестирование-rest-контроллеров-jackson), [7](#-7-кастомизация-jackson-object-mapper), [8](#user-content--8-тестирование-rest-контроллеров-через-jsonassert-и-матчеры)
6 | - Не стоит стремиться прочитать все ссылки урока, их можно использовать как справочник. Гораздо важнее пройти основной материал урока и сделать домашнее задание
7 | - Обязательно посмотри правила работы с патчами на проекте
8 | - Делать Apply Patch лучше по одному непосредственно перед видео на эту тему, а при просмотре видео сразу отслеживать все изменения кода проекта по изменению в патче (`Version Control -> Local Changes -> Ctrl+D`)
9 | - При первом Apply удобнее выбрать имя локального ченджлиста Name: Default. Далее все остальные патчи также будут в него попадать.
10 | - Код проекта обновляется и не всегда совпадает с видео (можно увидеть, как развивался проект). Изменения в проекте указываю после соответствующего патча.
11 |
12 | ##  Разбор домашнего задания HW6
13 |
14 | ###  1. HW6
15 | #### Apply 7_01_HW6_fix_tests.patch
16 |
17 | #### Apply 7_02_HW6_meals.patch
18 |
19 | > сделал фильтрацию еды через `get`: операция идемпотентная, можно делать в браузере обновление по F5
20 |
21 | ### Внимание: чиним пути в следующем патче
22 |
23 | #### Apply 7_03_HW6_fix_relative_url_utf8.patch
24 |
25 | -
26 | Relative paths in JSP
27 | -
28 | Spring redirect: prefix
29 |
30 | ###  2. HW6 Optional
31 |
32 | #### Apply 7_04_HW6_optional_add_role.patch
33 |
34 | #### `JdbcUserServiceTest` отвалились. Будем чинить в `7_06_HW6_jdbc_transaction_roles.patch`
35 |
36 | #### Apply 7_05_fix_hint_graph.patch
37 |
38 | - В `JpaUserRepositoryImpl.getByEmail` DISTINCT попадает в запрос, хотя он там не нужен. Это просто указание Hibernate
39 | не дублировать данные. Для оптимизации можно указать Hibernate делать запрос без
40 | distinct: [15.16.2. Using DISTINCT with entity queries](https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#hql-distinct)
41 | - Бага [HINT_PASS_DISTINCT_THROUGH does not work if 'hibernate.use_sql_comments=true'](https://hibernate.atlassian.net/browse/HHH-13280). При `hibernate.use_sql_comments=false` все работает - в SELECT нет DISTINCT.
42 | - Тест `DataJpaUserServiceTest.getWithMeals()` не работает для admin (у админа 2 роли, и еда при JOIN дублируется). ...
43 |
44 | #### Apply 7_06_HW6_jdbc_transaction_roles.patch
45 |
46 | Еще интересные JDBC реализации: ...
47 |
48 | ### Валидация для `JdbcUserRepository` через Bean Validation API
49 |
50 | #### Apply 7_07_HW6_optional_jdbc_validation.patch
51 |
52 | - [Валидация данных при помощи Bean Validation API](https://alexkosarev.name/2018/07/30/bean-validation-api/).
53 |
54 | На данный момент у нас реализована валидация сущностей только для jpa- и dataJpa-репозиториев. При работе
55 | через JDBC-репозиторий может произойти попытка записи в БД некорректных данных, что приведет к `SQLException` из-за нарушения
56 | ограничений, наложенных на столбцы базы данных. Для того чтобы перехватить невалидные данные еще до
57 | обращения в базу, воспользуемся API *javax.validation* (ее реализация `hibernate-validator` используется для проверки данных в Hibernate и будет использоваться в Spring Validation, которую подключим позже).
58 | В `ValidationUtil` создадим один потокобезопасный валидатор, который можно переиспользовать (см. *javadoc*).
59 | С его помощью в методах сохранения и обновления сущности в jdbc-репозиториях мы можем производить валидацию этой сущности: `ValidationUtil.validate(object);`
60 | Чтобы проверка не падала, `@NotNull Meal.user` пришлось пока закомментировать. Починим в 10-м занятии через `@JsonView`.
61 |
62 | ### Отключение кэша в тестах:
63 |
64 | Вместо наших приседаний с `JpaUtil` и проверкой профилей мы можем ...
65 |
66 | #### Apply 7_08_HW06_optional2_disable_tests_cache.patch
67 |
68 | - [Example of PropertyOverrideConfigurer](https://www.concretepage.com/spring/example_propertyoverrideconfigurer_spring)
69 | - [Spring util schema](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#xsd-schemas-util)
70 |
71 | ## Занятие 7:
72 |
73 | ###  3. Тестирование Spring MVC
74 |
75 |
76 | Краткое содержание
77 |
78 | #### Тестирование Spring MVC
79 |
80 | Для более удобного сравнения объектов в тестах мы будем использовать библиотеку *Harmcrest* с Matcher'ами, которая
81 | позволяет делать сложные проверки. С *JUnit* по умолчанию подтягивается *Harmcrest core*, но нам потребуется расширенная версия:
82 | в `pom.xml` из зависимости JUnit исключим дочернюю `hamcrest-core` и добавим `hamcrest-all`.
83 |
84 | Для тестирования web создадим вспомогательный класс `AbstractControllerTest`, от которого будут наследоваться все
85 | тесты контроллеров. Его особенностью будет наличие `MockMvc` - эмуляции Spring MVC для тестирования web-компонентов.
86 | Инициализируем ее в методе, отмеченном `@PostConstruct`:
87 |
88 | ```
89 | mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilter(CHARACTER_ENCODING_FILTER).build();
90 | ```
91 |
92 | Для того чтобы в тестах контроллеров не популировать базу перед каждым тестом, пометим этот базовый тестовый класс аннотацией `@Transactional`.
93 | Теперь каждый тестовый метод будет выполняться в транзакции, которая будет откатываться после окончания метода и возвращать базу данных в исходное
94 | состояние. Однако теперь в работе тестов могут возникнуть нюансы, связанные с пропагацией транзакций: все
95 | транзакции репозиториев станут вложенными во внешнюю транзакцию теста. При этом, например, кэш первого уровня станет работать не
96 | так, как ожидается. Т. е. при таком подходе нужно быть готовыми к ошибкам: мы их увидим и поборем в тестах на обработку ошибок на последних занятиях TopJava.
97 |
98 | #### UserControllerTest
99 |
100 | Создадим тестовый класс для контроллера юзеров, он должен наследоваться от `AbstractControllerTest`.
101 | В `MockMvc` используется [паттерн проектирования Builder](https://refactoring.guru/ru/design-patterns/builder).
102 |
103 | ```
104 | mockMvc.perform(get("/users")) // выполнить HTTP метод GET к "/users"
105 | .andDo(print()) // распечатать содержимое ответа
106 | .andExpect(status().isOk()) // от контроллера ожидается ответ со статусом HTTP 200(ok)
107 | .andExpect(view().name("users")) // контроллер должен вернуть view с именем "users"
108 | .andExpect(forwardedUrl("/WEB-INF/jsp/users.jsp")) // ожидается, что клиент должен быть перенаправлен на "/WEB-INF/jsp/users.jsp"
109 | .andExpect(model().attribute("users", hasSize(2))) // в модели должен быть атрибут "users" размером = 2 ...
110 | .andExpect(model().attribute("users", hasItem( // ... внутри которого есть элемент ...
111 | allOf(
112 | hasProperty("id", is(START_SEQ)), // ... с аттрибутом id = START_SEQ
113 | hasProperty("name", is(USER.getName())) //... и name = user
114 | )
115 | )));
116 | }
117 | ```
118 |
119 | В параметры метода `andExpect()` передается реализация `ResultMatcher`, в которой мы определяем, как должен быть обработан ответ контроллера.
120 |
121 |
122 |
123 | #### Apply 7_09_controller_test.patch
124 |
125 | > - в `MockMvc` добавился `CharacterEncodingFilter`
126 | > - добавил [`AllActiveProfileResolver`](//http://stackoverflow.com/questions/23871255/spring-profiles-simple-example-of-activeprofilesresolver) для возвращения массива профилей
127 | > - сделал вспомогательный метод `AbstractControllerTest.perform()`
128 |
129 | - Hamcrest
130 | - Unit Testing of Spring MVC Controllers
131 |
132 | ###  4. [Миграция на JUnit 5](https://drive.google.com/open?id=16wi0AJLelso-dPuDj6xaGL7yJPmiO71e)
133 |
134 |
135 | Краткое содержание
136 |
137 | Для миграции на 5-ю версию JUnit в файле `pom.xml` поменяем зависимость `junit` на `junit-jupiter-engine` ([No need `junit-platform-surefire-provider` dependency in `maven-surefire-plugin`](https://junit.org/junit5/docs/current/user-guide/#running-tests-build-maven)).
138 | Актуальную версию всегда можно посмотреть [в центральном maven-репозитории](https://search.maven.org/search?q=junit-jupiter-engine), берем только релизы (..-Mx означают предварительные milestone версии)
139 | Изменять конфигурацию плагина `maven-sureface-plugin` в новых версиях JUnit уже не требуется.
140 | JUnit5 не содержит в себе зависимости от *Harmcrest* (которую нам приходилось вручную
141 | отключать для JUnit4 в предыдущих шагах), поэтому исключение `hamcrest-core` просто удаляем.
142 | В итоге у нас останутся зависимости JUnit5 и расширенный Harmcrest.
143 | Теперь мы можем применить все нововведения пятой версии в наших тестах:
144 | 1. Для всех тестов теперь мы можем удалить `public`.
145 | 2. Аннотацию `@Before` исправим на `@BeforeEach` - теперь метод, который будет выполняться перед
146 | каждым тестом, помечается именно так.
147 | 3. В JUnit5 работа с исключениями похожа на JUnit4 версии 4.13: вместо ожидаемых исключений в параметрах аннотации `@Test(expected = Exception.class)` используется метод `assertThrows()`,
148 | в который первым аргументом мы передаем ожидаемое исключение, а вторым аргументом — реализацию функционального интерфейса `Executable` (код,
149 | в котором ожидается возникновение исключения).
150 | 4. Метод `assertThrows()` возвращает исключение, которое было выброшено в переданном ему коде. Теперь мы можем получить это исключение, извлечь из него сообщение с помощью
151 | `e.getMessage()` и сравнить с ожидаемым.
152 | 5. Для теста на валидацию при проверке предусловия, только при выполнении которого
153 | будет выполняться следующий участок кода (например, в нашем случае тесты на валидацию выполнялись
154 | только в jpa профиле), теперь нужно пользоваться утильным методом `Assumptions` (нам уже не требуется).
155 | 6. Проверку Root Cause - причины, из-за которой было выброшено пойманное исключение, мы будем делать позднее, при тестах на ошибки.
156 | 7. Из JUnit5 исключена функциональность `@Rule`, вместо них теперь нужно использовать `Extensions`, которые
157 | могут встраиваться в любую фазу тестов. Чтобы добавить их в тесты, пометим базовый тестовый класс аннотацией `@ExtendWith`.
158 |
159 | JUnit предоставляет нам набор коллбэков — интерфейсов, которые будут исполняться в определенный момент тестирования.
160 | Создадим класс `TimingExtension`, который будет засекать время выполнения тестовых методов.
161 | Этот класс будет имплементировать маркерные интерфейсы — коллбэки JUnit:
162 | - `BeforeTestExecutionCallback` - коллбэк, который будет вызывать методы этого интерфейса перед каждым тестовым методом.
163 | - `AfterTestExecutionCallback` - методы этого интерфейса будут вызываться после каждого тестового метода;
164 | - `BeforeAllCallback` - методы перед выполнением тестового класса;
165 | - `AfterAllCallback` - методы после выполнения тестового класса;
166 |
167 | Осталось реализовать соответствующие методы, которые описываются в каждом из этих интерфейсов, они и будут вызываться JUnit в нужный момент:
168 | - в методе `beforeAll` (который будет вызван перед запуском тестового класса) создадим спринговый утильный секундомер `StopWatch` для текущего тестового класса;
169 | - в методе `beforeTestExecution` (будет вызван перед тестовым методом) - запустим секундомер;
170 | - в методе `afterTestExecution` (будет вызван после тестового метода) - остановим секундомер.
171 | - в методе `afterAll` (который будет вызван по окончанию работы тестового класса) - выведем результат работы этого секундомера в лог;
172 |
173 | 8. Аннотации `@ContextConfiguration` и `@ExtendWith(SpringExtension.class)` (замена `@RunWith`) мы можем заменить одной `@SpringJUnitConfiguration` (старые версии IDEA ее не понимают)
174 |
175 |
176 |
177 | #### Apply 7_10_JUnit5.patch
178 |
179 | > - [No need `junit-platform-surefire-provider` dependency in `maven-surefire-plugin`](https://junit.org/junit5/docs/current/user-guide/#running-tests-build-maven)
180 | > - [Наконец пофиксили баг с `@SpringJUnitConfig`](https://youtrack.jetbrains.com/issue/IDEA-166549)
181 |
182 | - [JUnit 5 homepage](https://junit.org/junit5)
183 | - [Overview](https://junit.org/junit5/docs/snapshot/user-guide/#overview)
184 | - [10 интересных нововведений](https://habr.com/post/337700)
185 | - Дополнительно:
186 | - [Extension Model](https://junit.org/junit5/docs/current/user-guide/#extensions)
187 | - [A Guide to JUnit 5](http://www.baeldung.com/junit-5)
188 | - [Migrating from JUnit 4](http://www.baeldung.com/junit-5-migration)
189 | - [Before and After Test Execution Callbacks](https://junit.org/junit5/docs/snapshot/user-guide/#extensions-lifecycle-callbacks-before-after-execution)
190 | - [Conditional Test Execution](https://junit.org/junit5/docs/snapshot/user-guide/#writing-tests-conditional-execution)
191 | - [Third party Extensions](https://github.com/junit-team/junit5/wiki/Third-party-Extensions)
192 | - [Реализация assertThat](https://stackoverflow.com/questions/43280250)
193 |
194 | ###  5. [Принципы REST. REST контроллеры](https://drive.google.com/open?id=1e4ySjV15ZbswqzL29UkRSdGb4lcxXFm1)
195 |
196 |
197 | Краткое содержание
198 |
199 | #### Принципы REST, REST-контроллеры
200 |
201 | > [REST](http://spring-projects.ru/understanding/rest/) - архитектурный стиль проектирования распределенных систем (типа клиент-сервер).
202 |
203 | Чаще всего в REST-сервер и клиент общаются посредством обмена JSON-объектами через HTTP-методы GET/POST/PUT/DELETE/PATCH.
204 | Особенностью REST является отсутствие состояния (контекста) взаимодействий клиента и сервера.
205 |
206 | В нашем приложении есть контроллеры для Admin и для User. Чтобы сделать их REST-контроллерами,
207 | заменим аннотацию `@Controller` на `@RestController`
208 |
209 | > Не поленитесь зайти через Ctrl+click в `@RestController`: к аннотации `@Controller` добавлена `@ResponseBody`. Т. е. ответ от нашего приложения будет не View, а данные в теле ответа.
210 |
211 | В `@RequestMapping`, кроме пути для методов контроллера (`value`), добавляем параметр `produces = MediaType.APPLICATION_JSON_VALUE`.
212 | Это означает, что в заголовки ответа будет добавлен тип `ContentType="application/json"` - в ответе от контроллера будет приходить JSON-объект.
213 |
214 | > Чтобы было удобно использовать путь к этому контроллеру в приложении и в тестах,
215 | > выделим путь к нему в константу REST_URL, к которой можно будет обращаться из других классов
216 |
217 | 1. Метод `AdminRestController.getAll` пометим аннотацией `@GetMapping` - маршрутизация к методу по HTTP GET.
218 |
219 | 2. Метод `AdminRestController.get` пометим аннотацией `@GetMapping("/{id}")`.
220 | В скобках аннотации указано, что к основному URL контроллера будет добавляться `id` пользователя - переменная, которая передается в запросе непосредственно в URL.
221 | Соответствующий параметр метода нужно пометить аннотацией `@PathVariable` (если имя в URL и имя аргумента метода не совпадают, в параметрах аннотации дополнительно нужно будет уточнить
222 | имя в URL. Если они совпадают, [этого не требуется](https://habr.com/ru/post/440214/).
223 |
224 | 3. Метод создания пользователя `create` отметим аннотацией `@PostMapping` - маршрутизация к методу по HTTP POST.
225 | В метод мы передаем объект `User` в теле запроса (аннотация `@RequestBody`) в формате JSON (`consumes = MediaType.APPLICATION_JSON_VALUE`).
226 | При создании нового ресурса правило хорошего тона - вернуть в заголовке ответа URL созданного ресурса.
227 | Для этого возвращаем не `User`, а `ResponseEntity`, который мы можем с помощью билдера `ServletUriComponentsBuilder` дополнить заголовком ответа `Location` и вернуть статус `CREATED(201)`
228 | (если пойти в код `ResponseEntity.created` можно докопаться до сути, очень рекомендую смотреть в исходники кода).
229 |
230 | 4. Метод `delete` помечаем `@DeleteMapping("/{id}")` - HTTP DELETE.
231 | Он ничего не возвращает, поэтому помечаем его аннотацией `@ResponseStatus(HttpStatus.NO_CONTENT)`. Статус ответа будет HTTP.204;
232 |
233 | 5. Над методом обновления ставим `@PutMapping` (HTTP PUT). В аргументах метод принимает `@RequestBody User user` и `@PathVariable int id`.
234 |
235 | 6. Метод поиска по `email` также помечаем `@GetMapping` и, чтобы не было конфликта маршрутизации с методом `get()`,
236 | указываем в URL добавку `/by`. В этот метод `email` передается как параметр запроса (аннотация `@RequestParam`).
237 |
238 | > **Все это СТАНДАРТ архитектурного стиля REST. НЕ придумывайте ничего своего в своих выпускных проектах! Это очень большая ошибка - не придерживаться стандартов API.**
239 |
240 | 7. `ProfileRestController` выполняем аналогичным способом с учетом того, что пользователь имеет доступ только к своим данным.
241 |
242 | Если на данном этапе попытаться запустить приложение и обратиться к какому-либо методу контроллера, сервер ответит нам ошибкой со статусом 406,
243 | так как Spring не знает, как преобразовать объект User в JSON...
244 |
245 |
246 |
247 | #### Apply 7_11_rest_controller.patch
248 |
249 | - Понимание REST
250 | - JSON (JavaScript Object Notation)
251 | - [15 тривиальных фактов о правильной работе с протоколом HTTP](https://habrahabr.ru/company/yandex/blog/265569/)
252 | - [10 Best Practices for Better RESTful](https://medium.com/@mwaysolutions/10-best-practices-for-better-restful-api-cbe81b06f291)
253 | - [Best practices for rest nested resources](https://stackoverflow.com/questions/20951419/what-are-best-practices-for-rest-nested-resources)
254 | -
255 | Request mapping
256 | - [Лучшие практики разработки REST API: правила 1-7,15-17](https://tproger.ru/translations/luchshie-praktiki-razrabotki-rest-api-20-sovetov/)
257 | - Дополнительно:
258 | - [Подборка практик REST](https://gist.github.com/Londeren/838c8a223b92aa4017d3734d663a0ba3)
259 | - JAX-RS vs Spring MVC
260 | - RESTful API для сервера – делаем правильно (Часть 1)
261 | - RESTful API для сервера – делаем правильно (Часть 2)
262 | - И. Головач.
263 | RestAPI
264 | - [value/name в аннотациях @PathVariable и @RequestParam](https://habr.com/ru/post/440214/)
265 |
266 | ###  6. [Тестирование REST контроллеров. Jackson.](https://drive.google.com/open?id=1aZm2qoMh4yL_-i3HhRoyZFjRAQx-15lO)
267 |
268 |
269 | Краткое содержание
270 |
271 | Для работы с JSON добавляем в `pom.xml` зависимость `jackson-databind`.
272 | Актуальную версию библиотеки можно посмотреть в [центральном maven-репозитории](https://search.maven.org/artifact/com.fasterxml.jackson.core/jackson-databind).
273 | Теперь Spring будет автоматически использовать эту библиотеку для сериализации/десериализации объектов в JSON (найдя ее в *classpath*).
274 | Если сейчас запустить приложение и обратиться к методам REST-контроллера, то оно выбросит `LazyInitializationException`.
275 | Оно возникает из-за того, что у наших сущностей есть лениво загружаемые поля, отмеченные `FetchType.LAZY` - при загрузке сущности из базы вместо такого поля подставится Proxy, который и должен вернуть
276 | реальный экземпляр этого поля при первом же обращении. Jackson при сериализации в JSON использует все поля сущности,
277 | и при обращении к *Lazy*-полям возникает исключение, так как сессия работы с БД в этот момент уже закрыта, и нужный объект
278 | не может быть инициализирован. Чтобы Jackson игнорировал эти поля, пометим их аннотацией `@JsonIgnore`.
279 |
280 | Теперь при запуске приложения REST-контроллер будет работать. Но при получении JSON-объектов мы можем увидеть, что Jackson сериализовал объект
281 | через геттеры (например, в ответе есть поле `new` от метода `Persistable.isNew()`).
282 | Чтобы учитывались только поля объектов, добавим над `AbstractBaseEntity`:
283 | ````java
284 | @JsonAutoDetect(fieldVisibility = ANY, // jackson видит все поля
285 | getterVisibility = NONE, // ... но не видит геттеров
286 | isGetterVisibility = NONE, //... не видит геттеров boolean-полей
287 | setterVisibility = NONE) // ... не видит сеттеров
288 | ````
289 | Теперь все сущности, унаследованные от базового класса, будут сериализоваться/десериализоваться через поля.
290 |
291 |
292 |
293 | #### Apply 7_12_rest_test_jackson.patch
294 |
295 | - [Jackson databind github](https://github.com/FasterXML/jackson-databind)
296 | - [Jackson Annotation Examples](https://www.baeldung.com/jackson-annotations)
297 |
298 | ###  7. [Кастомизация Jackson Object Mapper](https://drive.google.com/open?id=1CM6y1JhKG_yeLQE_iCDONnI7Agi4pBks)
299 |
300 |
301 | Краткое содержание
302 |
303 | Сейчас, чтобы не сериализовать *Lazy*-поля, мы должны пройтись по каждой сущности и
304 | вручную пометить их аннотацией `@JsonIgnore`. Это неудобно, засоряет код и допускает возможные ошибки. К тому же,
305 | при некоторых условиях, нам иногда нужно загрузить и в ответе передать эти *Lazy*-поля.
306 | Чтобы запретить сериализацию Lazy-полей для всего проекта, подключим в `pom.xml` библиотеку `jackson-datatype-hibernate`.
307 | Также изменим сериализацию/десериализацию полей объектов в JSON: не через аннотацию `@JsonAutoDetect`, а в классе `JacksonObjectMapper`, который
308 | унаследуем от `ObjectMapper` (стандартный Mapper, который использует Jackson) и сделаем в нем другие настройки.
309 | В конструкторе:
310 | - регистрируем `Hibernate5Module` - модуль `jackson-datatype-hibernate`, который не делает сериализацию ленивых полей.
311 | - модуль для корректной сериализации `LocalDateTime` в поля JSON - `JavaTimeModule` модуль библиотеки `jackson-datatype-jsr310`
312 | - запрещаем доступ ко всем полям и методам класса и потом разрешаем доступ только к полям
313 | - не сериализуем null-поля (`setSerializationInclusion(JsonInclude.Include.NON_NULL)`)
314 |
315 | Чтобы подключить наш кастомный `JacksonObjectMapper` в проект, в конфигурации `spring-mvc.xml` к
316 | настройке `` добавим `MappingJackson2HttpMessageConverter`, который будет использовать наш маппер.
317 |
318 |
319 |
320 |
321 | #### Apply 7_13_jackson_object_mapper.patch
322 |
323 | - Сериализация hibernate lazy-loading с помощью
324 | jackson-datatype-hibernate
325 | - Handle Java 8 dates with Jackson
326 | - Дополнительно:
327 | - Jackson JSON
328 | Serializer & Deserializer
329 |
330 | ###  8. [Тестирование REST-контроллеров через JSONassert и Матчеры](https://drive.google.com/open?id=1oa3e0_tG57E71g6PW7_tfb3B61Qldctl)
331 |
332 |
333 | Краткое содержание
334 |
335 | Сейчас в тестах REST-контроллера мы проводим проверку только на статус ответа и тип возвращаемого контента. Добавим проверку содержимого ответа.
336 |
337 | #### 7_14_json_assert_tests
338 |
339 | Чтобы сравнивать содержимое ответа контроллера в виде JSON и сущность, воспользуемся библиотекой
340 | `jsonassert`, которую подключим в `pom.xml` со scope *test*.
341 |
342 | Эта библиотека при сравнении в тестах в качестве ожидаемого значения ожидает от
343 | нас объект в виде JSON-строки. Чтобы вручную не преобразовывать объекты в JSON и не
344 | хардкодить их в виде строк в наши тесты, воспользуемся Jackson.
345 | Для преобразования объектов в JSON и обратно создадим утильный класс `JsonUtil`, в котором
346 | с помощью нашего `JacksonObjectMapper` и будет конвертировать объекты.
347 | И мы сталкиваемся с проблемой: `JsonUtil` - утильный класс и не является
348 | бином Spring, а для его работы требуется наш кастомный маппер, который находится под управлением
349 | Spring и расположен в контейнере зависимостей. Поэтому, чтобы была возможность получить
350 | наш маппер из других классов, сделаем его синглтоном и сделаем в нем статический
351 | метод, который будет возвращать его экземпляр. Теперь `JsonUtil` сможет его получить.
352 | И нам нужно указать Spring, чтобы он не создавал второй экземпляр этого объекта, а клал в свой контекст существующий.
353 | Для этого в конфигурации `spring-mvc.xml` определим factory-метод, с помощью которого Spring должен
354 | получить экземпляр (instance) этого класса:
355 | ```xml
356 |
357 | ```
358 | а в конфигурации `message-converter` вместо создания бина просто сошлемся на сконфигурированный `objectMapper`.
359 |
360 | Метод `ContentResultMatchers.json()` из `spring-test` использует библиотеку `jsonassert` для сравнения 2-х JSON строк: одну из ответа контроллера и вторую -
361 | JSON-сериализация `admin` без поля `registered` (это поле инициализируется в момент создания и отличается).
362 | В методе `JsonUtil.writeIgnoreProps` мы преобразуем объект `admin` в мапу, удаляем из нее игнорируемые поля и снова сериализуем в JSON.
363 |
364 | Также сделаем тесты для утильного класса `JsonUtil`. В тестах мы записываем
365 | объект в JSON-строку, затем конвертируем эту строку обратно в объект и сравниваем с исходным. И то же самое делаем со списком объектов.
366 |
367 | #### 7_15_tests_refactoring
368 |
369 | **`RootControllerTest`**
370 |
371 | Сделаем рефакторинг `RootControllerTest`. Ранее мы в тесте получали модель, доставали из нее сущности и с помощью `hamcrest-all`
372 | производили по одному параметру их сравнение с ожидаемыми значениями.
373 | Метод `ResultActions.andExpect()` позволяет передавать реализацию интерфейса `Matcher`, в котором можно делать любые сравнения.
374 | Функциональность сравнения списка юзеров по ВСЕМ полям у нас уже есть - мы просто делегируем сравнение объектов в `UserTestData.MATCHER`.
375 | При этом нам больше не нужен `harmcrest-all`, нам достаточно только `harmcrest-core`.
376 |
377 | **`MatcherFactory`**
378 |
379 | Теперь вместо `jsonassert` и сравнения JSON-строк в тестах контроллеров сделаем сравнения JSON-объектов через `MatcherFactory`.
380 | Преобразуем ответ контроллера из JSON в объект и сравним с эталоном через уже имеющийся у нас матчер.
381 | Вместо сравнения JSON-строк в метод `andExpect()` мы будем передавать реализации интерфейса `ResultMatcher` из `MATCHER.contentJson(..)`.
382 |
383 | `MATCHER.contentJson(..)` принимают ожидаемый объект и возвращают для него `ResultMatcher` с реализацией единственного метода `match(MvcResult result)`,
384 | в котором делегируем сравнение уже существующим у нас матчерам.
385 | Мы берем JSON-тело ответа (`MatcherFactory.getContent`), десериализуем его в объект (`JsonUtil.readValue/readValues`) и сравниваем через имеющийся `MATCHER.assertMatch`
386 | десериализованный из тела контроллера объект и ожидаемое значение.
387 |
388 | > Методы из класса `TestUtil` перенес в `MatcherFactory`, лишние удалил.
389 |
390 | **`AdminRestControllerTest`**
391 |
392 | - `getByEmail()` - сделан по аналогии с тестом `get()`. Дополнительно нужно добавить в строку URL параметры запроса.
393 | - `delete()` - выполняем HTTP.DELETE. Проверяем статус ответа 204. Проверяем, что пользователь удален.
394 |
395 | > Раньше я получал всех users из базы и проверял, что среди них нет удаленного. При этом тесты становятся чувствительными ко всем users в базе и ломаются при добавлении/удалении новых тестовых данных.
396 |
397 | - `update()` - выполняем HTTP.PUT. В тело запроса подаем сериализованный `JsonUtil.writeValue(updated)`. После выполнения проверяем, что объект в базе обновился.
398 | - `create()` - выполняем HTTP.POST аналогично `update()`. Но сравнить результат мы сразу не можем, т. к. при создании объекта ему присваивается `id`.
399 | Поэтому мы извлекаем созданного пользователя из ответа (`MATCHER.readFromJson(action)`), получаем его `id`, и уже с этим `id` эталонный объект мы можем сравнить с объектом в ответе контроллера и со
400 | значением в базе.
401 | - `getAll()` - аналогично `get()`. Список пользователей из ответа в формате JSON сравниваем с эталонным списком (`MATCHER.contentJson(admin, user)`).
402 |
403 | Тесты для `ProfileRestController` выполнены аналогично.
404 |
405 |
406 |
407 | #### Apply 7_14_json_assert_tests.patch
408 |
409 | > - В `JsonUtil.writeIgnoreProps` вместо цикла по мапе сделал `map.keySet().removeAll`
410 |
411 | - [JSONassert](https://github.com/skyscreamer/JSONassert)
412 | - [Java Code Examples for ObjectMapper](https://www.programcreek.com/java-api-examples/index.php?api=com.fasterxml.jackson.databind.ObjectMapper)
413 |
414 | #### Apply 7_15_tests_refactoring.patch
415 |
416 | > - Методы из класса `TestUtil` перенес в `MatcherFactory`, лишние удалил.
417 | > - Раньше в тестах я для проверок получал всех users из базы и сравнивал с эталонным списком. При этом тесты становятся чувствительными ко всем users в базе и ломаются при добавлении/удалении новых тестовых данных.
418 |
419 | - [Java @SafeVarargs Annotation](https://www.baeldung.com/java-safevarargs)
420 |
421 | ###  9. Тестирование через SoapUI. UTF-8
422 |
423 |
424 | Краткое содержание
425 |
426 | SoapUI - это один из инструментов для тестирования API приложений, которые работают по REST и по SOAP.
427 | Он позволяет нам по протоколу HTTP дернуть методы нашего API и увидеть ответ контроллеров.
428 |
429 | Если в контроллер мы добавим метод, который в теле ответа будет возвращать текст на кириллице, то увидим, что кодировка теряется.
430 | Для сохранения кодировки используем `StringHttpMessageConverter`, который конфигурируем в `spring-mvc.xml`.
431 | При этом мы должны явно указать, что конвертор будет работать только с текстом в кодировке *UTF-8*.
432 |
433 |
434 |
435 | #### Apply 7_16_soapui_utf8_converter.patch
436 |
437 | - Инструменты тестирования REST:
438 | - SoapUI
439 | - Написание HTTP-запросов с помощью
440 | Curl.
441 | Для Windows 7 можно использовать Git Bash, с Windows 10 v1803 можно прямо из консоли. Возможны проблемы с UTF-8:
442 | - [CURL doesn't encode UTF-8](https://stackoverflow.com/a/41384903/548473)
443 | - [Нстройка кодировки в Windows](https://support.socialkit.ru/ru/knowledge-bases/4/articles/11110-preduprezhdenie-obnaruzhenyi-problemyi-svyazannyie-s-raspoznavaniem-russkih-simvolov)
444 | - **[IDEA: Tools->HTTP Client->...](https://www.jetbrains.com/help/idea/rest-client-tool-window.html)**
445 | - Postman
446 | - [Insomnia REST client](https://insomnia.rest/)
447 |
448 | **Импортировать проект в SoapUI из `config\Topjava-soapui-project.xml`. Response смотреть в формате JSON.**
449 |
450 | > Проверка UTF-8: http://localhost:8080/topjava/rest/profile/text
451 |
452 | [ResponseBody and UTF-8](http://web.archive.org/web/20190102203042/http://forum.spring.io/forum/spring-projects/web/74209-responsebody-and-utf-8)
453 |
454 | ##  Ваши вопросы
455 |
456 | > Зачем у нас и UI-контроллеры, и REST-контроллеры? То есть в общем случае backend-разработчику недостаточно предоставить REST API и RestController?
457 |
458 | В общем случае нужны и те, и другие. REST обычно используют для отдельного UI (например, на React или Angular) или для
459 | интеграции / мобильного приложения. У нас REST-контроллеры используются только для тестирования. UI-контроллеры используем для
460 | нашего приложения на JSP шаблонах. Таких сайтов без богатой UI логики тоже немало. Например https://javaops.ru/ :)
461 | Разница в запросах:
462 |
463 | - для UI используются только GET и POST
464 | - при создании/обновлении в UI мы принимаем данные из формы `application/x-www-form-urlencoded` (посмотрите
465 | вкладку `Network`, не в формате JSON)
466 | - для REST API запросы GET, POST, PUT, DELETE, PATCH и возвращают только данные (обычно JSON)
467 |
468 | ...и в способе авторизации:
469 |
470 | - для REST API у нас будет базовая авторизация
471 | - для UI - через cookies
472 |
473 | Также часто бывают смешанные сайты, где есть и отдельное JS приложение, и шаблоны.
474 |
475 | > При выполнении тестов через MockMvc никаких изменений на базе не видно, почему оно не сохраняет?
476 |
477 | `AbstractControllerTest` аннотируется `@Transactional` - это означает, что тесты идут в транзакции, и после каждого
478 | теста JUnit делает rollback базы.
479 |
480 | > Что получается в результате выполнения запроса `SELECT DISTINCT(u) FROM User u LEFT JOIN FETCH u.roles ORDER BY u.name, u.email`? В чем разница в SQL без `DISTINCT`.
481 |
482 | Запросы SQL можно посмотреть в логах. Т. е. `DISTINCT` в `JPQL` влияет на то, как Hibernate обрабатывает дублирующиеся
483 | записи (с `DISTINCT` их исключает). Результат можно посмотреть в тестах или приложении, поставив брекпойнт. По
484 | поводу `SQL DISTINCT` не стесняйтесь пользоваться google,
485 | например, [оператор SQL DISTINCT](http://2sql.ru/novosti/sql-distinct/)
486 |
487 | > В чем заключается расширение функциональности hamcrest в нашем тесте, что нам пришлось его отдельно от JUnit прописывать?
488 |
489 | hamcrest-all используется в проверках `RootControllerTest`: `org.hamcrest.Matchers.*`
490 |
491 | > Jackson мы просто подключаем в помнике, и Spring будет с ним работать без любых других настроек?
492 |
493 | Да, Spring смотрит в classpath и если видит там Jackson, то подключает интеграцию с ним.
494 |
495 | > Где-то слышал, что любой ресурс по REST должен однозначно идентифицироваться через url без параметров. Правильно ли задавать URL для фильтрации в виде `http://localhost/topjava/rest/meals/filter/{startDate}/{startTime}/{endDate}/{endTime}` ?
496 |
497 | Так делают только при
498 | отношении
499 | агрегация, например, если давать админу право смотреть еду любого юзера, URL мог бы быть похож
500 | на `http://localhost/topjava/rest/users/{userId}/meals/{mealId}` (не рекомендуется, см. ссылку ниже). В случае критериев
501 | поиска или страничных данных они передаются как параметр. Смотри также:
502 |
503 | - [15 тривиальных фактов о правильной работе с протоколом HTTP](https://habrahabr.ru/company/yandex/blog/265569/)
504 | - 10 Best Practices
505 | for Better RESTful
506 | - [REST resource hierarchy (если кратко: не рекомендуется)](https://stackoverflow.com/questions/15259843/how-to-structure-rest-resource-hierarchy)
507 |
508 | > Что означает конструкция в `JsonUtil`: `reader.readValues(json)`;
509 |
510 | См. Generic Methods. Когда компилятор
511 | не может вывести тип, можно его уточнить при вызове generic метода. Неважно, static или нет.
512 |
513 | ##  Домашнее задание HW07
514 |
515 | - 1: Добавить тесты контроллеров:
516 | - 1.1 `RootControllerTest.getMeals` для `meals.jsp`
517 | - 1.2 Сделать `ResourceControllerTest` для `style.css` (проверить `status` и `ContentType`)
518 | - 2: Реализовать `MealRestController` и протестировать его через `MealRestControllerTest`
519 | - 2.1 следите, чтобы url в тестах совпадал с параметрами в методе контроллера. Можно добавить
520 | логирование `` для проверки маршрутизации.
521 | - 2.2 в параметрах `getBetween` принимать `LocalDateTime` (конвертировать
522 | через @DateTimeFormat with Java
523 | 8 Date-Time API), пока без проверки на `null` (используя `toLocalDate()/toLocalTime()`, см. Optional п. 3). В
524 | тестах передавать в формате `ISO_LOCAL_DATE_TIME` (
525 | например `'2011-12-03T10:15:30'`).
526 |
527 | ### Optional
528 |
529 | - 3: Переделать `MealRestController.getBetween` на параметры `LocalDate/LocalTime` c раздельной фильтрацией по
530 | времени/дате, работающий при `null` значениях (см. демо и `JspMealController.getBetween`)
531 | . Заменить `@DateTimeFormat` на свои LocalDate/LocalTime конверторы или форматтеры.
532 | - Spring Type
533 | Conversion
534 | - Spring Field
535 | Formatting
536 | -
537 | Difference between Spring MVC formatters and converters
538 | - 4: Протестировать `MealRestController` (SoapUI, Curl, IDEA Test RESTful Web Service, Postman). Запросы `curl` занести
539 | в отдельный `md` файл (или `README.md`)
540 | - 5: Добавить в `AdminRestController` и `ProfileRestController` методы получения пользователя вместе с
541 | едой (`getWithMeals`, `/with-meals`).
542 | - [Jackson – Bidirectional Relationships](https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion)
543 |
544 | ### Optional 2
545 |
546 | - 6: Сделать тесты на методы контроллеров `getWithMeals()` (п. 5)
547 |
548 | **На следующем занятии используется JavaScript/jQuery. Если у вас там
549 | пробелы, пройдите его основы**
550 | ---------------------
551 |
552 | ##  Типичные ошибки и подсказки по реализации
553 |
554 | - 1: Ошибка в тесте _Invalid read array from JSON_ обычно расшифровывается немного ниже: читайте внимательно.
555 | - 2: Jackson и неизменяемые объекты (для
556 | сериализации `MealTo`)
557 | - 3: Если у meal, приходящий в контроллер, поля `null`, проверьте `@RequestBody` перед параметром (данные приходят в
558 | формате JSON)
559 | - 4: При проблемах с собственным форматтером убедитесь, что в конфигурации `[JVM Ecosystem Report 2021](https://snyk.io/jvm-ecosystem-report-2021/)
38 | >показывает, что Spring является абсолютным
39 | >лидером среди фреймворков.
40 |
41 | На первом месте упоминается **Spring Boot**, а на втором - **Spring MVC**.
42 |
43 | Здесь хотелось бы внести некоторую ясность.
44 | "Сердцем" Spring является Spring Core, который реализует Dependency
45 | Injection.
46 | Этот компонент, как правило, используется во всех остальных
47 | проектах Spring Framework.
48 |
49 | Spring Boot - это надстройка над Spring Framework,
50 | которая позволяет быстро создавать приложения разных типов,
51 | использовать автоматическую конфигурацию для некоторых
52 | компонентов и использовать некоторые удобные встроенные
53 | инструменты, например, готовые инструменты для мониторинга
54 | работы приложения (Spring Actuator).
55 |
56 | Если мы создаем web-приложение, то мы можем создавать его с
57 | помощью Spring Boot, но Spring MVC, который является именно
58 | web-фреймворком, также будет присутствовать в таком приложении
59 | и играть ключевую роль.
60 |
61 | Spring Boot позволяет создавать очень простые приложения без
62 | единой строчки конфигурации. Но как только мы пытаемся
63 | создать что-то более сложное, нам все равно приходится
64 | создавать конфигурационные файлы и классы и настраивать все вручную
65 | точно так же, как в традиционном Spring-приложении.
66 | По своему опыту могу сказать, что на реальных проектах
67 | такая ситуация возникает в большинстве случаев.
68 | Например, как только нужно настроить подключение
69 | к нескольким базам данных, а не к одной, мы вынуждены
70 | создавать конфигурационные классы вручную.
71 |
72 | В этом случае Spring Boot в какой-то степени может даже
73 | навредить вашей продуктивности, потому что вам придется
74 | разбираться, какие автоконфигурационные классы отключить, и т. д.
75 |
76 | Мы изучаем Spring довольно глубоко.
77 | Традиционно хорошо показал себя подход, при котором
78 | вначале изучается чистый Spring Framework, после чего
79 | мы переходим к использованию Spring Boot. Такой подход
80 | сохраняется и в этой версии курса. Без этого Spring Boot
81 | будет для вас "черным ящиком", который вам будет очень
82 | сложно понять, настраивать и отлаживать.
83 |
84 | ### ORM frameworks
85 | Отчеты, которые мы использовали, обычно не включают информацию
86 | о самых популярных ORM-фреймворках.
87 |
88 | >Известно,
89 | >что **Hibernate** является достаточно популярным фреймворком
90 | >и наиболее часто упоминается в вакансиях, если сравнивать
91 | >его с другими ORM-фреймворками и инструментами для работы Java-приложения
92 | >с базами данных.
93 |
94 | Вот одна из статей, которая также говорит о
95 | популярности Hibernate: [Top 5 Java ORM tools - 2022](https://www.knowledgefactory.net/2021/09/top-java-orm-tools-20XX.html)
96 |
97 | **ORM** или **Object-relational-mapping** можно перевести как
98 | "объектно-реляционное отображение (преобразование)".
99 | Это техника, которая позволяет создать виртуальную базу
100 | данных с помощью объектно ориентированного языка
101 | программирования и взаимодействовать с ней, в то время
102 | как взаимодействие уже с реальной базой данных выполняется
103 | фреймворком незаметно для нас.
104 | Это облегчает работу, позволяет работать с привычными
105 | и удобными для использования Java-объектами, вызывая
106 | их методы, вместо того, чтобы писать SQL-запросы к базе данных и код для интерпретации полученных данных.
107 |
108 | >Hibernate является реализацией спецификации JPA,
109 | >так же, как и менее популярный EclipseLink.
110 |
111 | Говоря простым языком, JPA (Java Persistence API) - это
112 | набор интерфейсов без реализации для работы с ORM,
113 | который включен в стандарт Java EE. Отдельные провайдеры
114 | могут предоставлять свои реализации этого интерфейса.
115 |
116 | Недостатками JPA и его реализации Hibernate являются удар по производительности
117 | и недостаточная гибкость. Вопрос производительности частично
118 | может быть решен с помощью различных техник оптимизации кода,
119 | написанного с использованием JPA, однако для некоторых
120 | приложений тот оверхед, который несет в себе JPA, является
121 | недопустимым, и вы можете увидеть на некоторых проектах
122 | использование других подходов, от использования
123 | чистого JDBC до использования MyBatis, JOOQ или каких-то
124 | альтернативных решений.
125 |
126 | В реальных приложениях те запросы к базе данных,
127 | которые создают наибольшую нагрузку на систему,
128 | могут быть оптимизированы для улучшения производительности: для
129 | них могут быть применены JDBC, альтернативные
130 | JPA-фреймворки, также запросы могут быть написаны
131 | с помощью нативных SQL-запросов в JPA.
132 | Для остальных запросов, которые не приводят к
133 | большой нагрузке на систему, в том же приложении может
134 | быть применен Hibernate.
135 | Таким образом, в одном приложении могут быть применены одновременно разные технологии.
136 |
137 |
138 | На курсе вы изучите, как работать с БД с помощью нескольких
139 | технологий: JDBC (а точнее, Spring JDBC template),
140 | а также JPA и Spring DataJPA.
141 | Вы сами не только увидите, но и почувствуете
142 | при написании кода в ваших домашних заданиях плюсы и минусы каждого подхода.
143 |
144 | ### Обзор пройденных тем
145 | Давайте подведем промежуточные итоги по результатам этого урока.
146 |
147 | В этом уроке мы:
148 |
149 | * познакомились с тем, что такое фреймворки
150 | и для чего они нужны;
151 | * посмотрели статистику, которая определяет
152 | Spring Framework как самый популярный фреймворк на рынке;
153 | * познакомились с ORM - подходом для упрощения работы
154 | с базами данных с использованием объектно-ориентированного подхода;
155 | * узнали про JPA (Java Persistence API) - протокол для работы с
156 | ORM - и про реализации JPA, среди которых Hibernate является самой популярной;
157 | * обсудили недостатки подхода ORM и познакомились с инструментами,
158 | которые могут быть использованы в качестве альтернативы.
159 |
160 | В следующем коротком уроке мы завершим обзор используемых технологий.
161 | Увидимся в следующем видео.
162 |
--------------------------------------------------------------------------------
/doc/video2.3.md:
--------------------------------------------------------------------------------
1 | ## Обзор наиболее востребованных технологий. Тренды
2 |
3 | ##  [Видео](https://drive.google.com/file/d/1XcTRkArj2guek9OiPuFEq_U1V4Dg0N-j)
4 |
5 | ### Тренд на отказ от reflection
6 |
7 | Говоря о трендах, хотелось бы сказать, что в настоящее
8 | время развиваются фреймворки, построенные на отказе
9 | от использования Reflection API.
10 | Dependency injection в Spring, сериализация с помощью
11 | Jackson построены на использовании Reflection, что
12 | сильно бьет по производительности, но было достаточно
13 | удобным решение до недавнего времени.
14 | Фреймворк Micronaut полностью построен на отказе от
15 | Reflection, и это дает существенный прирост
16 | производительности при измерении ряда параметров.
17 | Micronaut использует продвинутый компилятор и
18 | генерацию байткода, что позволяет создать все
19 | бины (управляемые фреймворком объекты) в ходе компиляции.
20 |
21 | Пока доля Micronaut очень мала, но он используется
22 | в продакшене. Я предполагаю, что в какой-то момент
23 | Spring может также внедрить подобный подход.
24 |
25 | ### Тренд на развитие реактивного программирования
26 |
27 | Продолжает развиваться реактивное программирование,
28 | которое является в какой-то степени новой парадигмой
29 | в программировании.
30 |
31 | Spring развивает свой реактивный фреймворк Spring WebFlux,
32 | который поддерживает библиотеку Reactor.
33 |
34 |
35 | Ряд современных задач не решается традиционными
36 | методами, такими как блокирующий Input/Output,
37 | HTTP-протокол. Одним из решений данных вопросов
38 | является применение подходов реактивного
39 | программирования (Reactor, RxJava), использование
40 | новых протоколов передачи данных (RSocket).
41 | У нас также готовится курс [ReactJava](https://javaops.ru/#inprogress) как
42 | продолжение TopJava на реактивном стеке.
43 |
44 | ### Тренд на микросервисы, тезисы
45 |
46 | ПО становиться большим и сложным. Очень большое приложение
47 | сложно поддерживать одной командой, управлять его жизненным
48 | циклом - разработкой, релизами.
49 |
50 | Если в большое монолитное приложение добавляется новая
51 | функциональность приходиться выполнять повторного тестирование
52 | всей большой системы, в результате срок выхода новых фич увеличивается.
53 |
54 | Микросервисная архитектура позволяет решить эту проблему - она
55 | предполагает разделение большого приложения на отдельные
56 | приложения-модули, которые взаимодействуют друг с другом.
57 | Над одним модулем-сервисом может работать один человек или
58 | небольшая команда. У такого модуля-сервиса будет отдельный
59 | Git-репозиторий, он может быть задеплоен (развернут) независимо
60 | от остальной системы. При таком подходе, команды могут вести работу
61 | над различными сервисами параллельно, параллельно деплоить
62 | их на серверах. При внесении изменений в микросервис “А”,
63 | вероятность вызывать проблемы в микросервисе “B” снижается.
64 | У разных микросервисов могут быть собственные базы данных.
65 | Это также повышает надежность и гибкость. Например, если по каким то причинам после обновления банковского микросервиса, ответственного за выдачу кредитов возникли сбои и база данных оказалась недоступна, другие компоненты системы, имеющие отдельные базы данных, продолжат свою работу без сбоев.
66 |
67 | Это существенно упрощает доработку, тестирование и деплой таких систем.
68 |
69 | Использование микросервисов дает большую гибкость в выборе
70 | технологий. Нам не нужно ограничивать себя в использовании
71 | технологий для того, чтобы все стандартизировать внутри
72 | одной большой системы. Работая с отдельными микросервисами,
73 | мы можем выбрать идеально подходящие технологии для отдельных задач.
74 | Например, один микросервис может использовать реляционные
75 | базы данных, а второй эффективнее решает свою задачу
76 | используя NoSQL базу данных или in memory базу данных.
77 |
78 | Еще одно важное преимущество, которое дает микросервисная
79 | архитектура это возможность легко масштабировать систему горизонтально.
80 |
81 | Предположим, что банк испытывает быстрый рост обращений
82 | об открытии новых счетов.
83 |
84 | Если банк использует монолитную архитектуру,
85 | то есть одно большое приложение, ему может потребоваться
86 | запускать отдельный экземпляр всего своего приложения
87 | и направлять часть обращений от клиентов на этот экземпляр (instance).
88 |
89 | Если же банк использует микросервисную архитектуру,
90 | он может запустить несколько экземпляров только сервиса,
91 | ответственного за открытие новых счетов и распределять
92 | нагрузку между этими экземплярами.
93 | При этом микросервис, ответственный за выдачу кредитов,
94 | который не испытывает повышенной нагрузки, может остаться
95 | в одном экземпляре. При этом увеличение числа микросервисов,
96 | ответственных за открытие счетов может происходить автоматически
97 | с помощью инструментов DevOps и Kubernetes.
98 |
99 | Однако использование микросервисов также создает сложности.
100 | Разработка систем, построенных на микросервисной архитектуре
101 | на порядок сложнее. Обслуживание таких систем также
102 | существенно сложнее.
103 |
104 | Компания должна обслуживать множество серверов,
105 | обеспечивать мониторинг каждого микросервиса и так далее.
106 | Также security таких систем существенно сложнее,
107 | поскольку мы имеем дело с множеством приложений,
108 | коммуницирующих друг с другом и все эти коммуникации
109 | должны быть безопасными.
110 |
111 |
112 | Следующий, готовый стать самым популярным
113 | после TopJava курс - [Микросервисы](https://javaops.ru/view/cloudjava).
114 |
115 | [Первое занятие открытое](https://javaops.ru/view/cloudjava/lesson01)
116 |
--------------------------------------------------------------------------------
/doc/video2.4.md:
--------------------------------------------------------------------------------
1 | ## 2.4 Обзор наиболее востребованных технологий. Обзор разрабатываемого приложения
2 |
3 | ##  [Видео](https://drive.google.com/file/d/1LHI18LZK1MRIEBpVe3WjCE890EydN5Gz)
4 |
5 | ### О работе с фронтендом и JavaScript
6 | Курс включает себя минимальную практику работы с JavaScript.
7 | Почему это нужно?
8 | В вакансиях backend разработчиков, как правило, отсутствуют
9 | требования глубокого знания JavaScript, но каждый разработчик
10 | должен уметь пользовать DevTools - инструментами разработчика
11 | в браузере, чтобы при работе над рабочими задачами по меньшей
12 | мере иметь возможность понять, происходит ли ошибка на стороне
13 | фронтенда или на стороне бэкенда, увидеть, какие данные уходят
14 | на сервер с фронтенда и так далее.
15 |
16 | Также, конечно, минимальные знания JavaScript приятны, поскольку
17 | они дают вам возможность написать свой несложный проект хотя
18 | бы с минимальным фронтендом.
19 |
20 | Существуют также fullstack-разработчики, от которых требуется
21 | способность полноценно решать задачи фронтенда на продакшене.
22 | Это требует довольно глубокого знания фронтенд-технологий и
23 | таких фреймворков, как Angular или React. Это требует много
24 | времени, и такая подготовка не входит в курс TopJava.
--------------------------------------------------------------------------------
/doc/video3.md:
--------------------------------------------------------------------------------
1 | ## Рекомендуемые подходы обучения на курсе
2 |
3 | ##  [Видео](https://drive.google.com/file/d/1v5sVL8ivNvSXEPVlrYibFLD5byywRkmT)
4 |
5 | В предыдущих уроках мы сделали обзор технологий,
6 | которые будут использоваться в нашем курсе и создаваемом проекте.
7 | Теперь давайте поговорим о том, как начать
8 | изучать эти технологии и практиковаться в их использовании.
9 |
10 | ---
11 | В 1980 году National Training Laboratories в
12 | США провели исследования эффективности разных
13 | способов обучения.
14 | Выяснилось, что у лекций и чтения книг крайне
15 | низкая эффективность — всего 5-10%.
16 | Дальше идет просмотр видео лекций и прослушивание аудио.
17 |
18 | Максимальная эффективность в 90% — это обучение
19 | людьми других людей — менторинг и немедленное
20 | применение полученных знаний на практике.
21 |
22 |
23 |
24 |
25 |
26 | Я хочу подчеркнуть этот момент.
27 |
28 | >Когда вы смотрите видео, вам может казаться, что вы все понимаете, но, поверьте, когда вы попытаетесь повторить это самостоятельно, у вас возникнет множество вопросов и сложностей. Практика - это важнейшая часть обучения, не пропускайте ее.
29 |
30 | На нашем курсе мы:
31 | - обсуждаем занятия с коллегами и преподавателями в Slack - эффективность 50%
32 | - выполняем практические домашние задания по каждой пройденной теме - 75%
33 | - помогаем коллегам и разрабатываем собственный выпускной проект - 90%
34 |
35 | ### О проверке домашних заданий
36 | Также очень важная часть обучения - проверка
37 | ваших домашних заданий и ревью выпускного
38 | проекта нашими кураторами.
39 |
40 | >**Это самый эффективный способ научиться программировать!**
41 |
42 | При устройстве на работу, на собеседовании обязательно
43 | задавай вопрос про ревью кода.
44 | Если его нет, фирма занимается разработкой
45 | непрофессионально? и рост там будет достаточно
46 | медленным и ограниченным.
47 |
48 | В ревью укажут именно твои ошибки
49 | в стиле, структурах данных, алгоритмах и кодировании.
50 | До вечера вторника участники шлют ссылку
51 | на свой GitHub-репозиторий с домашним
52 | заданием занятия, проверка делается
53 | ассистентами, результат пишется в Slack.
54 | Получается эффективно и оперативно.
55 |
56 | После проверки можно исправить замечания
57 | и пройти ее еще раз.
58 |
59 | В конце стажировки делается ревью вашего выпускного проекта.
60 |
61 |
62 | ### Участие на стажировке: ожидания и реальность
63 |
64 | Давайте кратко обсудим, чем курс TopJava является
65 | и чем он не является, что следует от него ожидать
66 | и чего не следует.
67 |
68 | #### 1-й тип ложного представления о стажировке:
69 |
70 | >Я увижу, как с нуля строится web-приложение A с использованием технологий B, просмотрю видео по темам, этого будет достаточно
71 |
72 |
73 |
74 | Почему такой подход не верный:
75 | TopJava - это стажировка, поэтому НЕ рассчитывайте
76 | пройти ее на диване с пакетом поп-корна.
77 | Тебе придется на ней РАБОТАТЬ (выполнять ДЗ,
78 | самостоятельно решать какие-то задачи, читать логи,
79 | дебажить, ходить на StackOverflow и даже думать
80 | об этом, засыпая)
81 |
82 | #### 2-й тип ложного представления о стажировке:
83 | >Меня научат шаблонам работы с технологией А, и я
84 | > смогу их применять в любой ситуации
85 |
86 | Почему это тоже не вполне верный подход:
87 | Используемые на стажировке технологии представляют
88 | собой инструменты, которые позволяет сделать
89 | что-то проще. Мы поделимся практикой их использования,
90 | неочевидными особенностями и т. п., покажем
91 | "грабли", на которые вы рано или поздно наступите.
92 | Нет гарантии, что, устроившись на работу, вы
93 | увидите точно такие же подходы.
94 | Все проекты и команды индивидуальны: используются
95 | различные инструменты и различные решения.
96 | Столкновение с технологиями, с которыми
97 | ты ранее не был знаком, - это нормальная
98 | часть жизни любого программиста. Нужно быть к этому готовым.
99 |
100 | Хорошее представление о решении проблем
101 | дает поиск на StackOverflow, где почти
102 | на любую проблему дается большое количество
103 | вариантов решения. Поиск решений и выбор
104 | лучшего - это основная работа Java-разработчика,
105 | и мы максимально постараемся этому научить:
106 | каждый раз в конкретной ситуации вы должны
107 | будете САМИ думать, что применять и как.
108 | Выполняя домашние задания, вы должны приложить
109 | все усилия, чтобы самостоятельно найти решение.
110 | Далее в начале следующего занятия вы также
111 | посмотрите разбор решения, подготовленного
112 | Григорием Кислиным.
113 |
114 | #### 3-й вариант ошибочного представления о стажировке TopJava связан с неверным представлением о том зачем нужна проверка домашних заданий. Например, человек может ошибочно рассуждать так:
115 |
116 | >я хочу проходить стажировку с проверкой ДЗ,
117 | > чтобы мне рассказали, как нужно правильно выполнять задания
118 |
119 | Задача проверки не в том, чтобы общими усилиями
120 | написать код, который ты и так увидишь в разборе.
121 | Если у тебя что-то не получается, наша
122 | задача - не найти ошибку/подебажить за тебя/почитать
123 | логи и т. п., а подсказать способ самостоятельно
124 | найти решение (хотя для этого мы сначала сами
125 | ищем/дебажим/читаем)
126 | Вторая важная задача, которую решает
127 | проверяющий, - увидеть то, что не увидел ты.
128 | Когда ты сдаешь задание на ревью, тебе
129 | может казаться, что все почти идеально. Проверяющий
130 | подскажет тебе, где ты что-то пропустил из-за
131 | недостатка опыта, что позволит тебе улучшить код.
132 |
133 | ---
134 |
135 | >Любое знание стоит воспринимать как подобие семантического дерева: убедитесь в том, что понимаете фундаментальные принципы, то есть ствол и крупные ветки, прежде чем лезть в мелкие листья-детали. Иначе последним не на чем будет держаться
136 | — Илон Маск
137 |
138 | Обычно в занятии дается много дополнительного
139 | материала и ссылок. Не стоит стремиться прочитать
140 | все ссылки урока, их можно использовать как
141 | справочник. Гораздо важнее пройти основной
142 | материал урока и сделать домашнее
143 | задание - этого достаточно для усвоения
144 | материала и получения той самой
145 | основы - ствола и крупных веток, на
146 | которых впоследствии можно наращивать листву.
147 |
148 |
149 | Как правило, подбираются участники разного
150 | уровня. Поэтому главное – не стеснятся
151 | задавать вопросы (после самостоятельного
152 | гугления и поиска решения). Всегда есть
153 | поддержка группы (в том числе от пришедших
154 | на бесплатный повтор участников), моя и ассистентов.
155 |
156 | ---
157 | ### Основные навыки программиста, которые необходимо развить на курсе
158 | Давайте перечислим набор навыков, которые
159 | вам необходимо развивать в ходе курса
160 | и которые необходимы любому программисту:
161 |
162 | - умение и привычка искать
163 | информацию, чтобы иметь больший выбор из
164 | доступных вариантов технологий и подходов
165 | к решению задачи, умение пользоваться StackOverflow;
166 | - умение пользоваться дебаггером в Intellij Idea;
167 | - умение пользоваться DevTools в браузере;
168 | - определенный кругозор и опыт для того, чтобы придумывать поисковые запросы.
169 |
--------------------------------------------------------------------------------
/doc/video4.md:
--------------------------------------------------------------------------------
1 | ## Структура приложения (многоуровневая архитектура)
2 | ##  [Видео](https://drive.google.com/file/d/1UHzSy9i-uonmTMFoR5v69Y-vyWLCLQWd)
3 |
4 | Приложение, которое мы будем разрабатывать, это [программа для подсчета калорий](http://javaops-demo.ru/topjava).
5 |
6 | В этом видео обсудим структуру этого приложения.
7 |
8 | ---
9 | Ссылки на отчеты, которые будут использоваться в этом уроке:
10 |
11 | - [Многоуровневая архитектура (русскоязыная статья в Wikipedia)](https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%BE%D0%B3%D0%BE%D1%83%D1%80%D0%BE%D0%B2%D0%BD%D0%B5%D0%B2%D0%B0%D1%8F_%D0%B0%D1%80%D1%85%D0%B8%D1%82%D0%B5%D0%BA%D1%82%D1%83%D1%80%D0%B0)
12 | - [Multitier architecture (англоязычная статья в Wikipedia)](https://en.wikipedia.org/wiki/Multitier_architecture)
13 |
14 | ---
15 |
16 |
17 |
18 | На структурной схеме приложения вы видите, что оно условно разделено на 4 части: **Views**,
19 | **Controller**, **Service** и **Repository**.
20 |
21 | Такой подход является реализацией многоуровневой архитектуры в программировании.
22 | По-английски этот подход называется **_Multitier architecture_**.
23 |
24 | Его суть заключается в разделении приложения на несколько слоев,
25 | каждый из которых ответственен за конкретную задачу.
26 |
27 | ### Слой отображения (View)
28 | Views соответствует слою отображения (или presentation layer). Это user interface (UI) или
29 | фронтенд - все то, что мы видим и с чем взаимодействуем в браузере.
30 | В качестве View могут быть HTML-страницы, созданные с использованием специальных
31 | движков шаблонов, например, JSP (встроен в Tomcat), или
32 | Thymeleaf (шаблоны по умолчанию в Spring Boot), или отдельное frontend-приложение,
33 | написанное на одном из JavaScript-фреймворков.
34 |
35 | В случае с движками шаблонов HTML-страницы будут располагаться в одном проекте
36 | с основным кодом приложения. Для приложений с "небогатым" UI используются именно шаблоны.
37 | Этот подход отличается от так называемых RIA - rich internet application - приложений со сложным UI.
38 |
39 | Главное отличие rich internet application от приложений с фронтендом
40 | на движках шаблонов заключается в том, что фронтенд, созданный на движке
41 | шаблонов, работает на сервере, и это что-то простое.
42 | В случае с rich internet application фронтенд-приложение загружается
43 | через Интернет к вам на компьютер и запускается в браузере.
44 | Оно может быть максимально сложным и выполнять функции традиционных
45 | десктоп-приложений.
46 | Иногда в одном приложении смешиваются оба способа: например, страница
47 | логина-пароля в RIA делаются на шаблонах.
48 |
49 | Создание простого фронтенда на движке шаблонов проще, поэтому
50 | в курсе мы будем использовать этот способ.
51 |
52 | ### Слой контроллеров (Controller)
53 | Следующий слой, который мы видим - это **Controller**.
54 |
55 | В многоуровневой архитектуре он соответствует слою, который
56 | называется "**_Слой приложения_**" или "**_Application layer_**").
57 | В GRASP (General Responsibility Assignment Software Patterns)
58 | он так и называется - Controller layer.
59 |
60 | Это слой приложения, который ответственен за обработку HTTP-запросов и проверку корректности входных данных. Если мы открываем главную страницу на сайте или отправляем заполненную на сайте форму, фронтенд-приложение отправляет HTTP-запрос серверу (в нашем случае контейнеру сервлетов), который принимает запрос и перенаправляет его в контроллер, соответствующий введенному в браузере URL или адресу, который вызывается при отправке формы через сайт.
61 | Также контроллеры могут принимать запросы не только от фронтенда, но и от других приложений.
62 |
63 | Слой контроллеров не имеет доступа к базе данных. Контроллеры общаются только с сервисами.
64 |
65 | ### Слой сервисов (Service layer)
66 | Слой **Service** на схеме приложения соответствует слою
67 | бизнес-логики (или **_Business layer_**) в многоуровневой архитектуре.
68 | В слое Service инкапсулирована вся бизнес-логика нашего приложения.
69 | Если коммуникация с фронтендом или другими приложениями - это ответственность контроллеров,
70 | то обработка данных - это ответственность сервисов.
71 |
72 | ### Слой доступа к данным (Data layer)
73 | Слой сервисов общается со слоем, ответственным за работу с базами данных.
74 | Этот слой называют **Data layer** (также можно встретить
75 | названия **Persistence Layer** или **Data access layer**), и он
76 | представлен в виде **_Data Access Object_** классов
77 | (коротко - **_DAO-классы_**) или классов, реализующих паттерн "репозиторий".
78 | С обоими видами классов вы попрактикуетесь в ходе курса.
79 | [Репозиторий - это также один из архитектурных паттернов](https://martinfowler.com/eaaCatalog/repository.html)
80 |
81 | Подобное разделение приложения на слои дает гибкость
82 | и существенно упрощает доработку и переиспользование приложения.
83 | Например, создав по такому принципу приложение,
84 | содержащее слои репозиториев, сервисов и контроллеров,
85 | мы в дальнейшем можем легко использовать это приложение
86 | с различными фронтенд-приложениями или мобильными приложениями.
87 | Если мы решим перейти на другую базу данных, мы можем
88 | переписать только слой репозиториев, и нам не требуется
89 | вносить изменения в слои сервисов и контроллеров.
90 |
91 | >Для маленького приложение такой подход может показаться
92 | >избыточно сложным, но по мере расширения это является спасением.
93 |
94 | Подавляющее большинство реальных приложений построено с использованием именно этой архитектуры.
95 |
96 | ### Краткие итоги
97 | В этом видео мы познакомились с концепцией многоуровневой архитектуры,
98 | которую мы применим при создании приложения на курсе.
99 | Многоуровневая архитектура предполагает разделение приложения на слои:
100 | - Views - слой отображения является фронтендом;
101 | - Controller - слой приложения ответственен за прием и валидацию входных данных;
102 | - слой Service включает в себя весь код, отражающий бизнес логику;
103 | - Repository или Data layer отвечает за взаимодействие с базой данных.
104 |
105 | Также мы обсудили какие преимущества дает такой подход.
106 | Среди преимуществ в первую очередь возможность повторного
107 | использования различных слоев и упрощение их доработки и изменения.
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/doc/video5-vcs-git.md:
--------------------------------------------------------------------------------
1 | ## Системы управления версиями, Git
2 | ##  [Видео](https://drive.google.com/file/d/1uFjIsxsaSAXxFSwSpjJIGK7Ug2VXf6yH)
3 |
4 | video5-vcs-git.md
5 |
6 | В этом уроке мы рассмотрим системы управления версиями
7 | и самую популярную из них - Git.
8 |
9 | ---
10 | * [StackOverflow 2021 survey](https://insights.stackoverflow.com/survey/2021#technology-most-popular-technologies)
11 | * [Введение в Git и GitHub: установка и настройка](https://topjava.ru/blog/vvedeniye-v-git-github-ustanovka-i-nastroyka)
12 | * [Введение в Git и GitHub: базовые команды](https://topjava.ru/blog/vvedeniye-v-git-github-bazovyye-komandy)
13 | * [Введение в Git и GitHub: ошибки использования](https://topjava.ru/blog/vvedeniye-v-git-oshibki-ispolzovaniya-ch-9)
14 | * [Бесплатная русскоязычная книга Pro Git](https://git-scm.com/book/ru/v2/)
15 | ---
16 |
17 | Git является де-факто стандартом среди систем управления версиями.
18 | Опрос, проведенный StackOverflow в 2021 году показывает,
19 | что Git используют почти 95% опрошенных разработчиков.
20 |
21 | Когда-то популярная централизованная система контроля
22 | версий SVN (Subversion) практически полностью заменена Git.
23 | Но некоторые большие проекты все еще используют SVN.
24 | Примером такого проекта является WordPress.
25 | Я также все еще иногда встречаю SVN в вакансиях российских компаний.
26 |
27 | ### Что такое Git и GitHub
28 | В ходе курса мы будем использовать Git.
29 | Git - это распределенная система управления версиями.
30 | Это означает, что код, над которым работает команда,
31 | и ранее сохраненные (закоммиченные) версии проекта
32 | хранится на компьютерах каждого члена команды,
33 | а также в удаленном репозитории, который можно
34 | сравнить с облачным хранилищем.
35 |
36 | Некоторые путают Git и GitHub, но это не одно и то же.
37 |
38 | **Git** — это утилита, которую
39 | программист устанавливает у себя на компьютере для
40 | сохранения состояний проектов и контроля версий проекта.
41 |
42 | **GitHub** — это провайдер удаленных репозиториев,
43 | сайт (хостинг) для хранения кода проекта и его изменений,
44 | для обмена файлами с членами команды проекта.
45 | Программисты могут создавать на GitHub публичные репозитории,
46 | в которых код доступен всем. Компании могут приобрести платный
47 | аккаунт на GitHub и вести свои проекты в закрытых репозиториях,
48 | доступ к которым имеют только члены команды проекта.
49 | Существуют и другие подобные сайты - провайдеры удаленных
50 | репозиториев, например, BitBucket, SourceForge, GitLab и т. д.
51 |
52 |
53 | ### Как работают Git и GitHub
54 |
55 |
56 | Говоря кратко, работа с Git и удаленным репозиторием
57 | (в нашем случае это Github) выглядит следующим образом.
58 |
59 | Первый разработчик, который начинал работу над проектом,
60 | использовал команду **_git init_** в корневой директории
61 | проекта для того, чтобы инициализировать пустой Git-репозиторий.
62 | В этот момент Git создает в директории с проектом скрытую
63 | директорию, содержащую файлы, необходимые для его работы.
64 | Теперь первый разработчик может с помощью команды **_git add_**
65 | добавлять файлы проекта в индекс - то есть в зону,
66 | отслеживаемую git, а также может фиксировать изменения,
67 | создавая коммиты (**_git commit_**), и загружать их в
68 | удаленный репозиторий (например, на GitHub) с помощью
69 | команды **_git push_**.
70 |
71 | Спустя некоторое время к работе над проектом подключается второй разработчик.
72 |
73 | Поскольку первый разработчик пушил изменения файлов проекта
74 | на удаленный репозиторий, второй разработчик может скачать
75 | их себе на компьютер с помощью команды **_git pull_**
76 | и продолжить работу с учетом этих изменений.
77 |
78 | Давайте повторим.
79 | В описанной работе использовались команды:
80 |
81 | * **_git init_** - эта команда инициализирует работу Git
82 | для конкретного проекта. В папке с проектом создается
83 | скрытая папка, хранящая все файлы, необходимые Git
84 | для работы. Папка с этими файлами впоследствии будет
85 | загружена в удаленный репозиторий, и второй программист,
86 | скачавший проект, увидит у себя на компьютере все ранее
87 | созданные с помощью Git версии.
88 | * **_git add_** - это команда, которая добавляет файлы
89 | проекта в индекс (или отслеживаемую зону), чтобы их можно
90 | было в какой-то момент закоммитить (то есть сохранить, зафиксировать).
91 | * **_git commit_** - сохраняет все файлы проекта в
92 | текущем состоянии так, что мы в любой момент сможем
93 | вернуться к этому состоянию - посмотреть, как изменились
94 | файлы, или даже полностью вернуть проект к состоянию
95 | данного коммита.
96 | * **_git push_** - загружает файлы в удаленный Git-репозиторий,
97 | чтобы их могли скачать другие программисты.
98 | * **_git pull_** используют для того, чтобы скачать
99 | файлы из удаленного репозитория себе на компьютер.
100 |
101 | Также Git позволяет создавать ветки. Это означает,
102 | что вы можете создать копию стабильного кода и
103 | продолжить работу в этой копии, не подвергая риску
104 | стабильную версию. Когда код с новой функциональностью
105 | готов, отлажен и протестирован, он может быть
106 | слит ("смержен", от слова "merge") в основную ветку со стабильным кодом.
107 |
108 | С помощью этих функций Git позволяет команде разработчиков
109 | работать одновременно над разными задачами и поддерживать
110 | код в стабильном состоянии.
111 |
112 | Также Git позволяет в любой момент понять, кто и когда внес
113 | изменения в определенный код, что существенно упрощает взаимодействия
114 | с коллегами. Например, в случае, если вы видите новые
115 | строки кода, которые вызывают у вас вопросы, с помощью
116 | Git вы можете разобраться, кто внес изменения именно
117 | в эти строки, и связаться с этим человеком
118 | для уточнения деталей.
119 |
120 | Если произошла ситуация, при которой два разработчика
121 | изменили один и тот же файл, Git потребует от вас вручную
122 | отрегулировать такой конфликт.
123 |
124 | Также благодаря Git у вас всегда под рукой детальная
125 | история изменений. С помощью комментариев к коммитам
126 | вы можете детально документировать ход работы над
127 | проектом и в случае необходимости разобраться, в
128 | какой момент что-то пошло не так, и откатиться
129 | к той версии, где ошибка еще не была сделана.
130 | Или просто выяснить, как выглядел код определенного
131 | класса или метода в определенной версии и внести правки
132 | в текущую версию, если это необходимо.
133 |
134 | ### Дополнительные материалы
135 |
136 | Для изучения Git рекомендуем в первую очередь ознакомиться со статьями на сайте [topjava.ru](https://topjava.ru):
137 |
138 | * [Введение в Git и GitHub: установка и настройка](https://topjava.ru/blog/vvedeniye-v-git-github-ustanovka-i-nastroyka)
139 | * [Введение в Git и GitHub: базовые команды](https://topjava.ru/blog/vvedeniye-v-git-github-bazovyye-komandy)
140 | * [Введение в Git и GitHub: ошибки использования](https://topjava.ru/blog/vvedeniye-v-git-oshibki-ispolzovaniya-ch-9)
141 |
142 | В них дается детальная инструкция по первоначальной настройке
143 | Git, GitHub, в том числе инструкция по настройке
144 | Access token в GitHub, что вам обязательно нужно будет сделать.
145 |
146 | Также можно упомянуть официальную русскоязычную книгу Pro Git,
147 | которая доступна [бесплатно в электронном виде](https://git-scm.com/book/ru/v2/).
148 |
149 | ### Как мы будем использовать Git на курсе
150 | В Git очень много команд, но в ходе курса мы будем использовать
151 | только самые необходимые из них.
152 | С git можно работать как через терминал с помощью команд,
153 | так и с помощью различных программ с графическим интерфейсом.
154 | Мы будем преимущественно использовать интеграцию
155 | IntelliJ Idea с Git, поскольку она очень удобна
156 | и существенно упрощает работу.
157 | Однако знать, как выполнять аналогичные операции
158 | в терминале, очень полезно.
159 |
160 | ### Резюме
161 | В этом уроке мы сделали краткий обзор систем управления
162 | версиями и самой популярной из них - Git:
163 |
164 | * разобрались в различиях Git и GitHub.
165 | Git - это система контроля версий, а
166 | GitHub - провайдер удаленных репозиториев, один из многих, доступных на рынке.
167 | * кратко познакомились с тем, как Git работает.
168 | Узнали о командах git init, git add, git commit, git push и git pull.
169 | * Также мы обсудили, что такое ветки и какие возможности они дают.
170 |
171 | ---
172 |
173 | Если вы не работали раньше с Git, не беспокойтесь.
174 | В последующих уроках работа с Git будет изучаться
175 | на практике в ходе работы над проектом. Но дополнительно
176 | почитать о Git все же стоит.
177 |
178 |
179 |
180 |
181 |
--------------------------------------------------------------------------------
/graduation.md:
--------------------------------------------------------------------------------
1 | ## Выпускной проект [стажировки TopJava](https://javaops.ru/view/topjava)
2 |
3 | Design and implement a REST API using Spring-Boot/Spring Data JPA **without frontend**.
4 |
5 | The task is:
6 |
7 | Build a voting system for deciding where to have lunch.
8 |
9 | * 2 types of users: admin and regular users
10 | * Admin can input a restaurant and it's lunch menu of the day (2-5 items usually, just a dish name and price)
11 | * Menu changes each day (admins do the updates)
12 | * Users can vote for a restaurant they want to have lunch at today
13 | * Only one vote counted per user
14 | * If user votes again the same day:
15 | - If it is before 11:00 we assume that he changed his mind.
16 | - If it is after 11:00 then it is too late, vote can't be changed
17 |
18 | Each restaurant provides a new menu each day.
19 |
20 | As a result, provide a link to github repository. It should contain the code, README.md with API documentation and couple curl commands to test it (**better - link to Swagger**).
21 |
22 | -----------------------------
23 | P.S.: Make sure everything works with latest version that is on github :)
24 | P.P.S.: Assume that your API will be used by a frontend developer to build frontend on top of that.
25 |
26 | -----------------------------
27 |
28 | ##  Рекомендации
29 |
30 | **Пишем выпускной проект как тестовое задание на работу**
31 |
32 | - **Не изобретай велосипедов!** Грубая ошибка - пытаться сделать стандартные вещи по-своему, чаще всего криво. На проекте все должно быть единообразно! Ваш проект TopJava - сделай все МАКСИМАЛЬНО в этом
33 | стиле. Если тебе кажется, что есть лучшее решение, чем в TopJava - пишите мне в личку, я всегда открыт для улучшений.
34 | - **Рекомендую писать проект на востребованном на рынке стеке**: Spring Boot + Spring Data JPA (работа с БД) + Swagger/OpenAPI 3.0 (REST документация).
35 | - **Оптимально подойдет код миграции TopJava на Spring Boot в конце стажировки или [курса BootJava](https://javaops.ru/view/bootjava)**
36 |
37 | *Представьте себе, что ПМ (лид, архитектор) дал вам ТЗ и некоторое время недоступен. У вас, конечно, есть много мыслей, для чего нужно приложение, как исправить ТЗ, дополнить его и сделать правильно.
38 | НО НЕ НАДО ИХ РЕАЛИЗОВЫВАТЬ В КОДЕ. Нужно сделать все строго по ТЗ, максимально просто, удобно для доработок и для использования со стороны клиента.*
39 |
40 | > Совершенство достигнуто не тогда, когда нечего добавить, а тогда, когда нечего отнять
41 |
42 | _Антуан де Сент-Экзюпери_
43 |
44 | ### 1: ТЗ (Тех.задание)
45 |
46 | - 1.1: Читай ТЗ ОЧЕНЬ внимательно, НЕ надо ничего своего туда домысливать и творчески изменять
47 | - 1.2: Учитывай, что пользователей может быть ОООЧЕНЬ много, а админов - МАЛО
48 | - 1.3: Сначала сделай основные сценарии по ТЗ. Все остальное (если очень хочется, 3 раза подумай) - потом.
49 |
50 | ### 2. API
51 |
52 | - 2.1: API продумывай с точки зрения не программиста и объектов, а с точки зрения того, кто им будет пользоваться (клиента, UI)
53 | - 2.1: Тщательно считайте количество запросов в вашем API для отображения нужной информации
54 | - 2.3: Из потребностей приложения (клиента) реализуй только очевидные сценарии. Необходимо и достаточно: ВСЕ НЕОБХОДИМОЕ для клиента и НИЧЕГО ЛИШНЕГО. Процесс творческий, приходит с опытом.
55 | - 2.4: Делаем REST API в соответствии с концепцией REST (url в общем имеют вид`{ресурс}/{id_ресурсa}[/{подресурс}/{id_подресурсa}][параметры]`, см. ниже ссылки про REST и иерархию). Имена ресурсов во множественном числе!
56 | Самая распространенная и грубая ошибка - не придерживаться этих простых правил.
57 | - **[15 тривиальных фактов о правильной работе с протоколом HTTP](https://habrahabr.ru/company/yandex/blog/265569/)**
58 | - **[10 Best Practices for Better RESTful API](https://medium.com/@mwaysolutions/10-best-practices-for-better-restful-api-cbe81b06f291)**
59 | - **[REST resource hierarchy](https://stackoverflow.com/questions/20951419/what-are-best-practices-for-rest-nested-resources)**
60 | - [Лучшие практики разработки REST API: правила 1-7,15-17](https://tproger.ru/translations/luchshie-praktiki-razrabotki-rest-api-20-sovetov/)
61 | - 2.5: Разделение на роли я предпочитаю на уровне URL. Сразу и однозначно видно, какой API у админа, какое у пользователя (API админа начинается, например, с */admin/...*).
62 | - 2.6: На управление (CRUD) ресторанами и едой должны быть ОТДЕЛЬНЫЕ контроллеры. Не надо все, что может админ, сваливать в одну кучу! Смотрите на результат операции - помещаете в этот контроллер!
63 | - 2.7: Проверьте в Swagger, что в POST и PUT нет ничего лишнего, а в GET есть все необходимые данные. Например, при запросе голоса должен в ответе отображаться `id` ресторана, а не весь объект, при создании-редактировании ресторана в примерах swagger не должно быть меню и еды.
64 | - 2.8: `Profile` означает, что данные принадлежат профилю пользователя. Все остальное называйте по-другому.
65 | - 2.9: Отсутствие данных часто бывает "бизнес кейсом", те НЕ ошибкой в запросе или приложении. Исключение - это ошибка, например неверный `id`. Запрос на данные, которые могут быть, могут нет, не должен приводить к исключениям. Посмотрите в сторону `ResponseEntity.of()`
66 | - 2.10: По REST URL должно быть однозначно понятно, какие будут параметры на входе и что ждать на выходе. Без сюрпризов!
67 |
68 | ### 3: Код:
69 | - 3.1: Строго соблюдайте соглашения Java по именованию: пакеты ТОЛЬКО маленькими буквами, методы начинаются с маленькой буквы, классы с большой. Незнания Java Core - тестовое задание сразу в корзину.
70 | - 3.2 В проекте (и тестовом задании на работу), в отличие от нашего учебного topjava, оставляйте только необходимый для работы по ТЗ приложения код, ничего лишнего
71 | - 3.2.1: НЕ надо делать разные профили базы и работы с ней
72 | - 3.2.2: НЕ надо делать абстрактных контроллеров на всякий случай
73 | - 3.2.3: НЕ надо делать сервисов, если там нет ничего, кроме делегирования
74 | - 3.2.4: НЕ нужны локализация, UI, типы ошибок, Json View
75 | - 3.3: Название пакетов, имен классов для `model/to/web` стандартные (например `model/domain`). НЕ надо придумывать своих собственных правил
76 | - 3.4: Проверьте, не торчат ли из кода учебные уши TopJava, типа `ProfileRestController.testUTF()`, `AbstractServiceTest.printResult()` или закомментированные `JdbcTemplate`. Назначение выпускного
77 | совсем другое
78 | - 3.5: Вместо `return ResponseEntity.ok(object)` в контроллерах пишите `return object`. Проще!
79 |
80 | ### 4: Модель
81 |
82 | - 4.1: В БД обычно хранятся все введенные пользователем и админом данные c возможность их редактирования. Это означает, что мы не удаляем прошлые меню, а храним их в базе, как и историю голосования. Есть базовые вещи, которые закладываются в архитектуру приложения, и есть неочевидные доработки к ТЗ, делать не надо.
83 | - 4.2: Не делайте в модели объектов, которые не будут использоваться в коде (например, не надо двунаправленных связей, если достаточно однонаправленных)
84 | - 4.3: еще раз про [hashCode/equals в Entity](https://stackoverflow.com/questions/5031614/the-jpa-hashcode-equals-dilemma): не делайте в модели сравнение по полям!
85 | - 4.4: ORM работает с объектами. [Иногда, для упрощения логики, fk_id как поля допустимы](https://stackoverflow.com/questions/6311776/hibernate-foreign-keys-instead-of-entities)
86 |
87 | ### 5: Архитектура / pom
88 | - 5.1: Можно:
89 | - или подключить DATA-REST (см.курс [Spring Boot 2.x + HATEOAS](https://javaops.ru/view/bootjava)). Контроллеры генерируются автоматически по репозиториям, требуется настройка ресурсов в кастомных контроллерах
90 | - **РЕКОМЕНДУЕТСЯ** делать на основе миграции TopJava / кода [курса BootJava](https://javaops.ru/view/bootjava)
91 |
92 | Нельзя смешивать эти подходы вместе! Я рекомендую 2-й вариант, без data-rest. Обязательно посмотрите в Swagger, какие контроллеры получились в результате.
93 | - 5.2: Не размещайте бизнес-логику приложения и преобразования в TO в слое доступа к DB
94 | - 5.3: Не смешивайте TO и Entity вместе. Они должны быть независимыми друг от друга. На TopJava мы смотрели разные варианты [c использованием TO и без](https://stackoverflow.com/a/21569720/548473).
95 | Делаем максимально просто.
96 | - 5.4: [Use for money in java app](http://stackoverflow.com/a/43051227/548473)
97 | - 5.5 Не надо явно указывать версии зависимостей в `pom`, если они наследуются от `spring-boot-starter-parent`
98 |
99 | ### 6: Доступ к БД
100 |
101 | - 6.1: Используйте Spring Data JPA (без лишней делегации). Методы Repository можно вызывать напрямую из сервиса или из контроллера.
102 | - 6.2: В DATA-JPA 2.x используются `Optional`. Попробуйте работать с ними, это безопасный способ работать с null-значениями (используйте `orElseThrow`)
103 | - 6.3: Не делайте при обновлении записи ради экономии пары строчек кода так:
104 | ```
105 | if(updateCondition)
106 | repository.delete(entity)
107 | }
108 | repository.save(entity)
109 | ```
110 | Обновление записи базы должно быть через `UPDATE`.
111 |
112 | ### 7: База Данных
113 |
114 | - 7.1: Берите без установки (H2 или HSQLDB). Одну и **в памяти**! Ваше приложение должно сразу запуститься, без всяких настроек и переменных окружения
115 | - 7.2: Тщательно считайте количество обращений в базу на каждый запрос. Особенно при запросах от юзеров, которых очень много! Также на сложность запросов от них, чтобы не положить базу
116 | - 7.3: Сделайте [индексы к таблицам](https://ru.wikipedia.org/wiki/Индекс_(базы_данных)). Попробуйте обеспечить UNIQUE (один голос пользователя в день, один уникальный пункт меню в день).
117 | Следите за **порядком полей в индексе**, от этого зависит индексирование запросов.
118 | - 7.4: При популировании добавь записи за сегодняшний день - `now()`, чтобы всегда были актуальные исходные данные
119 | - 7.5: Поля базы case insensitive, не пишите camelStyle (для которых нужны кавычки)
120 | - 7.6: Таблицы обычно именуются в единственном числе. Исключение - `users`, `orders` и другие зарезервированные слова
121 | - 7.7: `date`/`timestamp` - зарезервированное слово, лучше избегать их при именовании полей
122 |
123 | ### 8: Security
124 |
125 | - 8.1: Проверьте, станет ли код проще с `@AuthenticationPrincipal` (урок 11, доступ к AuthorizedUser).
126 | - 8.2: Я предпочитаю четкое разделение ролей на основе URL. Для админа URL содержит `/admin`
127 | - 8.3: Еще раз - призываю не менять код TopJava
128 |
129 | ### 9: Кэширование
130 |
131 | - 9.1: Кэширование желательно для частых и редко меняющихся запросов от пользователей.
132 | Тщательно продумайте, что надо кэшировать (самые частые запросы), а что нет (большие или редко запрашиваемые данные)
133 | - 9.2: Проверьте соответствие ключей к кэшу (параметры кэшируемого метода) с конфигурацией (например в singleNonExpiryCache, heap=1 в кэше может содержаться только ОДНО значение).
134 |
135 | ### 10: Валидация
136 |
137 | - 10.1: Одних аннотаций валидации на полях недостаточно. Должны быть `@Valid/@Validation` в контроллере
138 | - 10.2: Прячте `id` при `create/update` в примерах Swagger. Если их передали - проверяйте на соответствие (в TopJava это `ValidationUtil.checkNew()/assureIdConsistent()`)
139 |
140 | ### 11: Дополнительно
141 |
142 | - 11.1: По возможности сделать JUnit-тесты. Можно не делать 100% покрытие, только основные сценарии
143 | - 11.2: Уделяйте внимание обработке ошибок.
144 |
145 | ### 12: `readme.md`:
146 |
147 | - 12.1: Поместите вначале `readme` ТЗ или **ссылку на него** - будет понятно о чем твой проект
148 | - 12.2: Если задание на English, описание пиши также на English (то же самое относится к языку резюме: вакансия на English предполагает резюме на English)
149 | - 12.3: Требуемые примеры `curl` не прячьте, а пишите здесь! Оптимально сделать **ссылку на `Swagger UI` с креденшелами для выполнения запросов**
150 | - 12.4: Проверяют люди с опытом в Java: не надо писать инструкций, как устанавливать Java и Maven
151 |
152 | ### 13: Git
153 |
154 | - 13.1: Должна быть история ваших комитов с внятными комментариями. Это смотрят.
155 | > Эйчар обращает внимание на дату создания аккаунта и то, как в него заливались коммиты (элементы проекта), постепенно или в один день, насколько технологии в аккаунте коррелируют с технологиями в резюме
156 | - 13.2: Не комить служенбые файлы: логи, DB, настройки IDEA и пр., это сразу - уровень Junior.
157 | - 13.3: Все служебные файлы должны быть в `.gitignore`
158 |
159 | ## Проверка
160 |
161 | - Попробуй подергать свое API по всем типичным сценариям ТЗ!
162 | - Удобно использовать? Можно сделать проще? Например, чтобы проголосовать за ресторан залогиненному юзеру, достаточно `restorauntId`.
163 | - Сколько раз пришлось его вызвать API для типичного сценария (например посмотреть рестораны с едой на сегодня)?
164 | - Сколько запросов к базе было сделано? Можно ли сократить (например с `FETCH/Graph` или через кэширование)?
165 | - **Еще раз - проверь все запросы в Sawgger, смотри на формат запросов и данные в ответе. Все должно работать, есть все данные и нет ничего лишнего**
166 | - 13.2: API ДОЛЖЕН соответствовать принципам REST (см. ссылки выше)
167 | - 13.3: ОБЯЗАТЕЛЬНО: запустите `mvn test` - ошибок быть не должно
168 | - 13.4: ОБЯЗАТЕЛЬНО: запустите приложение без всяких предварительных настроек (базы, переменных окружения, ..), лучше на другом компьютере. Приложение должно запускаться и работать!
169 |
170 | ## Оценка
171 | ТЗ очень скромное, не дает понимания, что хочет получить заказчик, именно поэтому моих комментариев к этому ТЗ больше на 2 порядка. Это реальное тестовое задание на работу. При оценке учитывается отсутствие грубых ляпов, простота и красота решения + его расширяемость, если понадобится дорабатывать приложение. Если практический опыт небольшой, еще раз очень рекомендую держаться как можно ближе к нашему коду на Spring Boot.
172 | Тестовое задание дается для того, чтобы оценить вас, как программиста. Нужны ли вы компании или нет. Это умение спроектировать грамотную модель и API, придерживаясь принципов REST и без своих велосипедов, и ваш чистый красивый код.
173 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 |
5 | ru.javawebinar
6 | topjava
7 | jar
8 |
9 | 1.0-SNAPSHOT
10 |
11 | Calories Management
12 | https://javaops-demo.ru/topjava
13 |
14 |
15 | 1.8
16 | UTF-8
17 | UTF-8
18 |
19 |
20 |
21 | topjava
22 | install
23 |
24 |
25 | org.apache.maven.plugins
26 | maven-compiler-plugin
27 | 3.14.0
28 |
29 | ${java.version}
30 | ${java.version}
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/main/java/ru/javawebinar/topjava/Main.java:
--------------------------------------------------------------------------------
1 | package ru.javawebinar.topjava;
2 |
3 | /**
4 | * @see Demo application
5 | * @see Initial project
6 | */
7 | public class Main {
8 | public static void main(String[] args) {
9 | System.out.format("Hello TopJava Enterprise!");
10 | }
11 | }
12 |
--------------------------------------------------------------------------------