Всем привет!
Вернемся к проблеме “n + 1”, о которой я недавно делала пост. Там я рассказала об одном соблазнительном, но неправильном решении. Кстати сказать, один раз я применила его летом в одном из ТЗ Я.Практикума. Тогда мне ревьюер интересно ответила, что раньше бы она сказала на fetch eager, что это 100% нельзя использовать, но сейчас у них тимлид заставляет всех использовать fetch eager на проекте. То есть можно представить, какая нагрузка идет на базу данных, когда ВСЕ запросы идут, как n + 1, правда?
Какие есть правильные решения?
1. Использовать JOIN FETCH в аннотации @Query:
Хочу сказать интересную вещь про join fetch.
Возможно это для всех сразу стало очевидным, когда они первый раз прочитали про join fetch, но я об этом узнала только вчера. Оказывается join fetch — это inner join fetch, то есть если нам нужно соединение left join, то нужно указывать left join fetch. Я этого не знала, на дипломе в таких случаях использовала запросы на нативном SQL в @Query. Об @EntityGraph я также не знала еще неделю-две назад, ее еще не применяла на практике. Но в этой статье можно посмотреть примеры, как ее нужно применять.
Вернемся к проблеме “n + 1”, о которой я недавно делала пост. Там я рассказала об одном соблазнительном, но неправильном решении. Кстати сказать, один раз я применила его летом в одном из ТЗ Я.Практикума. Тогда мне ревьюер интересно ответила, что раньше бы она сказала на fetch eager, что это 100% нельзя использовать, но сейчас у них тимлид заставляет всех использовать fetch eager на проекте. То есть можно представить, какая нагрузка идет на базу данных, когда ВСЕ запросы идут, как n + 1, правда?
Какие есть правильные решения?
1. Использовать JOIN FETCH в аннотации @Query:
@Query(value = "" +2. Использовать аннотацию @EntityGraph над методом в репозитории:
"SELECT c FROM Course c " +
" JOIN FETCH c.lessons")
List<Course> findAll();
@EntityGraph(attributePaths = {"lessons"})
List<Course> findAllUsingEntityGraph();
В аргументе attributePaths аннотации @EntityGraph указывается тот объект, который необходимо инициализировать сразу, несмотря на установленный у него ленивый тип загрузки.Хочу сказать интересную вещь про join fetch.
Возможно это для всех сразу стало очевидным, когда они первый раз прочитали про join fetch, но я об этом узнала только вчера. Оказывается join fetch — это inner join fetch, то есть если нам нужно соединение left join, то нужно указывать left join fetch. Я этого не знала, на дипломе в таких случаях использовала запросы на нативном SQL в @Query. Об @EntityGraph я также не знала еще неделю-две назад, ее еще не применяла на практике. Но в этой статье можно посмотреть примеры, как ее нужно применять.
👍3🔥2
Всем привет!
Хочу сегодня поделиться интересным видео по дебагу. Это было для меня последнее видео из курса со степика, на этом теоретическую часть я закончила, останется только дописать проект.
Тема видео кажется несложной, всем известной. Я сама сначала сомневалась, стоит ли его смотреть, подумав, что про дебаг я знаю много, сколько багов отловила у себя в программах, даже несколько раз отлавливала баги в чужом коде. Но все-таки решила посмотреть, чтобы закончить с теорией и перейти к оставшейся части.
Не пожалела, узнала много новых фишек, поняла, что есть ещё больше, о чем не рассказали в видео. Поэтому решила посоветовать его здесь, может кому-нибудь пригодится 😊
А я пока вернусь к Spring Security in Action, осталось до конца совсем немного, потом буду смотреть в документации замены для устаревших методов (на выходных научилась это искать там) и буду дописывать свою курсэру (тру-сэру? или, может, трус-курс? 🤣).
Хочу сегодня поделиться интересным видео по дебагу. Это было для меня последнее видео из курса со степика, на этом теоретическую часть я закончила, останется только дописать проект.
Тема видео кажется несложной, всем известной. Я сама сначала сомневалась, стоит ли его смотреть, подумав, что про дебаг я знаю много, сколько багов отловила у себя в программах, даже несколько раз отлавливала баги в чужом коде. Но все-таки решила посмотреть, чтобы закончить с теорией и перейти к оставшейся части.
Не пожалела, узнала много новых фишек, поняла, что есть ещё больше, о чем не рассказали в видео. Поэтому решила посоветовать его здесь, может кому-нибудь пригодится 😊
А я пока вернусь к Spring Security in Action, осталось до конца совсем немного, потом буду смотреть в документации замены для устаревших методов (на выходных научилась это искать там) и буду дописывать свою курсэру (тру-сэру? или, может, трус-курс? 🤣).
YouTube
Летняя школа 2021 - Бэкенд разработка, воркшоп 6
Запись воркшопа - "Debug". Ментор - Денис Тимофеев.
05.08.2021
05.08.2021
🔥6😁2👍1
Всем привет!
Как-то писала, что реализовывала Spring Security с дополнительным фильтром на JWT, но не написала, что такое JWT.
Хочу сегодня это исправить 👨💻 Для тех, кто не знает, надеюсь будет интересно, а кто знает, надеюсь, поправит меня, если я где-то ошибусь 😊
Итак, как вообще расшифровывается JWT? Расшифровывается, как JSON Web Token.
Как он выглядит?
Примерно, вот так (новые строчки добавлены для удобства чтения):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Это своего рода закодированное сообщение. По условному разделению по строкам, верхняя строка означает заголовок, в нем может быть указано при помощи какого алгоритма выполняется хеширование подписи. Посередине — полезная информация, в ней может находиться username, id и/или роли пользователя, или что-то другое, что мы захотим добавить. А третья часть — это подпись, которая кодируется при помощи секретного ключа.
Каждая часть кодируется отдельно при помощи алгоритма base64url, соединяется через точку и хешируется при помощи алгоритма из заголовка, выглядит это так:
На официальном сайте, можно попробовать создать свой JWT. Если изменить хоть один символ в токене, то уже не пройдет проверку на соответствие на сервере.
Что нужно иметь в виду еще. Нужно на сервере обязательно проверять весь токен полностью, не только, условно, хедер. Например, прочитала в официальной брошюре-книге, что злоумышленник может указать в заголовке, что, мол, токен без подписи, пропускай мой запрос.
Поэтому, если мы хотим сохранить безопасность доступа, нужно проверять токен полностью, вместе с подписью, а также лучше делать его коротким по продолжительности жизни. В этом случае, как прочитала в комментариях у этой статьи про JWT на хабре, можно организовать автообновление токена с помощью oAuth2. До oAuth2 я еще пока не дошла, поэтому пока как на деле это сделать не знаю.
Как-то писала, что реализовывала Spring Security с дополнительным фильтром на JWT, но не написала, что такое JWT.
Хочу сегодня это исправить 👨💻 Для тех, кто не знает, надеюсь будет интересно, а кто знает, надеюсь, поправит меня, если я где-то ошибусь 😊
Итак, как вообще расшифровывается JWT? Расшифровывается, как JSON Web Token.
Как он выглядит?
Примерно, вот так (новые строчки добавлены для удобства чтения):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Это своего рода закодированное сообщение. По условному разделению по строкам, верхняя строка означает заголовок, в нем может быть указано при помощи какого алгоритма выполняется хеширование подписи. Посередине — полезная информация, в ней может находиться username, id и/или роли пользователя, или что-то другое, что мы захотим добавить. А третья часть — это подпись, которая кодируется при помощи секретного ключа.
Каждая часть кодируется отдельно при помощи алгоритма base64url, соединяется через точку и хешируется при помощи алгоритма из заголовка, выглядит это так:
HMACSHA256(
base64UrlEncode(заголовок/header) + "." +
base64UrlEncode(полезная инфа/payload),
наш-256-битный-секрет
)
На официальном сайте, можно попробовать создать свой JWT. Если изменить хоть один символ в токене, то уже не пройдет проверку на соответствие на сервере.
Что нужно иметь в виду еще. Нужно на сервере обязательно проверять весь токен полностью, не только, условно, хедер. Например, прочитала в официальной брошюре-книге, что злоумышленник может указать в заголовке, что, мол, токен без подписи, пропускай мой запрос.
Поэтому, если мы хотим сохранить безопасность доступа, нужно проверять токен полностью, вместе с подписью, а также лучше делать его коротким по продолжительности жизни. В этом случае, как прочитала в комментариях у этой статьи про JWT на хабре, можно организовать автообновление токена с помощью oAuth2. До oAuth2 я еще пока не дошла, поэтому пока как на деле это сделать не знаю.
JSON Web Tokens - jwt.io
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
🔥4👍1
Всем привет!)
О мотивации пост.
Вчера пришла мысль, что меня очень мотивирует в изучении java и всего, что с ней связано (где-то о java говорят в мужском роде, мне почему-то хочется говорить в женском, надеюсь это вкусовщина, а не моя ошибка 😅).
Мысль меня посетила после лекции, которая закончилась уже вечером, а мне сильно захотелось заняться программированием и прямо так, чуть ли не всю ночь кодить. Задалась вопросом и поняла, что меня очень мотивируют крутые специалисты. Когда смотрю, как они программируют или рассказывают о чем-то в чем хорошо разбираются - это меня завораживает.
Один раз был смешной случай, как-то случайно по ссылке посмотрела час лекции по математике, там были сложные вычисления, что-то из продвинутого уровня, ничего не поняла, но не могла отвести взгляда)) после этого записалась на этот курс (бесплатный), но к сожалению не мой уровень.
Пыталась было с попроще видео на ютюбе зайти, но всё равно не вышло и решила не отвлекаться пока от программирования. Когда-нибудь возможно вернусь ещё)
А вас что мотивирует? 😊
О мотивации пост.
Вчера пришла мысль, что меня очень мотивирует в изучении java и всего, что с ней связано (где-то о java говорят в мужском роде, мне почему-то хочется говорить в женском, надеюсь это вкусовщина, а не моя ошибка 😅).
Мысль меня посетила после лекции, которая закончилась уже вечером, а мне сильно захотелось заняться программированием и прямо так, чуть ли не всю ночь кодить. Задалась вопросом и поняла, что меня очень мотивируют крутые специалисты. Когда смотрю, как они программируют или рассказывают о чем-то в чем хорошо разбираются - это меня завораживает.
Один раз был смешной случай, как-то случайно по ссылке посмотрела час лекции по математике, там были сложные вычисления, что-то из продвинутого уровня, ничего не поняла, но не могла отвести взгляда)) после этого записалась на этот курс (бесплатный), но к сожалению не мой уровень.
Пыталась было с попроще видео на ютюбе зайти, но всё равно не вышло и решила не отвлекаться пока от программирования. Когда-нибудь возможно вернусь ещё)
А вас что мотивирует? 😊
🔥5
Всем привет!
Хочу сегодня поделиться впечатлениями со стажировки. У нас выстраивается интересный большой проект. Пока там 4 сервиса, но модулей уже 6. Один модуль, dependency_bom, имеет в себе только pom.xml файл, в котором прописаны все зависимости в dependencyManagement и все версии этих зависимостей в properties.
Другой модуль содержит в себе чисто скрипты миграции для наполнения и откатывания разных изменений базы данных. Когда сама подключала Liquibase в своем проекте, сделала это по-другому, подключила в каждом модуле. Вариант с отдельным модулем понравился больше по удобству, так что возможно это отрефакторю в своём проекте тоже. Но пока там приоритет другой - настроить взаимодействие сервисов по OAuth2, но об этом попозже.
На стажировке нам нужно теперь прописывать работу с базой данных, и, что для меня новое, нужно будет в одном или нескольких сервисах использовать myBatis, вместо Hibernate.
MyBatis выглядит чуть сложнее в настройке с непривычки, хотя вроде он должен быть проще. Ему нужно прописывать связи и запросы в xml, либо использовать одну из последних версий, где добавили аннотации. Поизучаю, пока буду делать задание.
В целом, мне всё очень нравится, вижу много пользы для себя. Потом расскажу подробнее про свое изучение OAuth2, его пока только начала (читаю последние главы Spring Security in Action).
Хочу сегодня поделиться впечатлениями со стажировки. У нас выстраивается интересный большой проект. Пока там 4 сервиса, но модулей уже 6. Один модуль, dependency_bom, имеет в себе только pom.xml файл, в котором прописаны все зависимости в dependencyManagement и все версии этих зависимостей в properties.
Другой модуль содержит в себе чисто скрипты миграции для наполнения и откатывания разных изменений базы данных. Когда сама подключала Liquibase в своем проекте, сделала это по-другому, подключила в каждом модуле. Вариант с отдельным модулем понравился больше по удобству, так что возможно это отрефакторю в своём проекте тоже. Но пока там приоритет другой - настроить взаимодействие сервисов по OAuth2, но об этом попозже.
На стажировке нам нужно теперь прописывать работу с базой данных, и, что для меня новое, нужно будет в одном или нескольких сервисах использовать myBatis, вместо Hibernate.
MyBatis выглядит чуть сложнее в настройке с непривычки, хотя вроде он должен быть проще. Ему нужно прописывать связи и запросы в xml, либо использовать одну из последних версий, где добавили аннотации. Поизучаю, пока буду делать задание.
В целом, мне всё очень нравится, вижу много пользы для себя. Потом расскажу подробнее про свое изучение OAuth2, его пока только начала (читаю последние главы Spring Security in Action).
🔥10
Всем привет!
А знаете ли вы?
Что, оказывается, Hibernate не оптимизирует запросы, если ему дать запрос в native query. Вместо одного запроса с джоинами, он может сделать несколько запросов. Вчера опытным путем на это наткнулась.
А ещё оказалось, что если поставить @Lob над полем у сущности, с типом данных TEXT в базе данных, как в некоторых статьях советуют, Hibernate может ошибочно подумать, что это long и пытаться распарсить текст, как цифру, и выдавать ошибку DataIntegrityConflict.
Долго же я вчера искала почему хибернейт пытался подставить текст в идентификатор 😅 а оказалось дело было в @Lob.
Кстати, в книжке недавно прочитала такое наставление для новичков, сейчас уместно, как никогда об этом рассказать - "никогда не используйте в коде что-то, когда не знаете наверняка, что это делает и как работает" 😊
А знаете ли вы?
Что, оказывается, Hibernate не оптимизирует запросы, если ему дать запрос в native query. Вместо одного запроса с джоинами, он может сделать несколько запросов. Вчера опытным путем на это наткнулась.
А ещё оказалось, что если поставить @Lob над полем у сущности, с типом данных TEXT в базе данных, как в некоторых статьях советуют, Hibernate может ошибочно подумать, что это long и пытаться распарсить текст, как цифру, и выдавать ошибку DataIntegrityConflict.
Долго же я вчера искала почему хибернейт пытался подставить текст в идентификатор 😅 а оказалось дело было в @Lob.
Кстати, в книжке недавно прочитала такое наставление для новичков, сейчас уместно, как никогда об этом рассказать - "никогда не используйте в коде что-то, когда не знаете наверняка, что это делает и как работает" 😊
👍8
Всем привет!
Меня вчера почти победил MyBatis. Никак не получалось настроить его через xml. Уже почти сдалась и написала своему проверяющему может не надо его настраивать, но он сказал надо) Но вроде не обязательно через xml. Написала бин, через класс конфигурации, написала метод с аннотациями. Заработало наполовину.
Пошла смотреть в интернет, что же я упускаю, результат неправильно собирался из базы. Все дополнительные поля, получающиеся от соединений (left join), не маппились, а получались null.
Снова попыталась прописать маппинг через xml, потом попалась аннотация result. Нашла хорошую статью с применением этой аннотации, применила у себя. Получилось со второго раза и, наконец я победила этот myBatis!
Но может быть надо научиться и через xml его настраивать. Но пока надо выполнить следующее задание к понедельнику. Подключить и применить RabbitMQ, а ещё Feign.
Про feign я до этого не слышала. Мы на курсе использовали restTemplate для общения микросервисов. Там клиента создавали, помню не с первого раза у меня получалось, прописывала заголовки, замысловатый конструктор для клиента. А у коллег с курса этот клиент никак не хотел инжектиться по autowire.
Feign же настраивается с помощью пары аннотаций и выглядит как огромное упрощение по сравнению с restTemplate. От нас требуется только поставить аннотацию, разрешающую feign и прописать интерфейс с нужными аннотациями, а имплементация за нас будет сделана во время работы нашего приложения.
Ссылка на статью о Feign.
Меня вчера почти победил MyBatis. Никак не получалось настроить его через xml. Уже почти сдалась и написала своему проверяющему может не надо его настраивать, но он сказал надо) Но вроде не обязательно через xml. Написала бин, через класс конфигурации, написала метод с аннотациями. Заработало наполовину.
Пошла смотреть в интернет, что же я упускаю, результат неправильно собирался из базы. Все дополнительные поля, получающиеся от соединений (left join), не маппились, а получались null.
Снова попыталась прописать маппинг через xml, потом попалась аннотация result. Нашла хорошую статью с применением этой аннотации, применила у себя. Получилось со второго раза и, наконец я победила этот myBatis!
Но может быть надо научиться и через xml его настраивать. Но пока надо выполнить следующее задание к понедельнику. Подключить и применить RabbitMQ, а ещё Feign.
Про feign я до этого не слышала. Мы на курсе использовали restTemplate для общения микросервисов. Там клиента создавали, помню не с первого раза у меня получалось, прописывала заголовки, замысловатый конструктор для клиента. А у коллег с курса этот клиент никак не хотел инжектиться по autowire.
Feign же настраивается с помощью пары аннотаций и выглядит как огромное упрощение по сравнению с restTemplate. От нас требуется только поставить аннотацию, разрешающую feign и прописать интерфейс с нужными аннотациями, а имплементация за нас будет сделана во время работы нашего приложения.
Ссылка на статью о Feign.
🔥9
Всем привет!
Сегодня такой баг отловила, такой баг. Потратила даже не знаю сколько времени на него и он такой простой оказался, что решила поделиться и рассказать про свое приключение😅
В общем, подключала сегодня Feign клиента, того самого, который подключается-то за одну аннотацию у людей с прямыми руками😁
Подключаю нужную зависимость, даже убираю транзитивную с уязвимостью, ставлю нужную аннотацию, @EnableFeignClients, завожу интерфейс с нужным клиентом, ставлю над ним аннотацию @FeignClient, прописываю ему имя в скобках и url по которому будет отправлен запрос. Запускаю - ошибка "необходимо указать имя или значение для FeignClient".
Перехожу на свой клиент, перечитываю ещё раз, что у меня написано имя, меняю на value - ошибка та же.
Пошла в гугл, посмотрела разные статьи, документацию, указываешь произвольное имя в скобках аннотации и всё, как говорит amigoscode из YouTube - job done.
Сегодня смотрела его курс по микросервисам, там тоже было подключение Feign клиента, добавила как у него в @EnableFeignClients в скобках basePackage и указала где искать моего клиента. Та же ошибка.
Спрашиваю чат gpt, подсказывает мне подключить другую зависимость дополнительно, попробовала - безрезультатно. Пошла снова в гугл, попробовала разные версии зависимостей, разные дополнительные зависимости. "Нет имени или значения" и все тут.
В один момент, когда игралась с версиями зависимостей подключила несовместимую с Java 11 и ошибка появилась другая и открылось место, где была моя ошибка.
Как бы вы думали, в чем она была?
Оказалось, что я сначала создала клиента для другого сервиса, поставила над ним аннотацию, но не стала настраивать, потому что захотела сначала настроить другой клиент для другого сервиса. И, конечно, же, у него действительно не было ни имени ни значения в параметрах аннотации, ведь я пока не собиралась его использовать.
Ну вот как так можно? 😅
Сегодня такой баг отловила, такой баг. Потратила даже не знаю сколько времени на него и он такой простой оказался, что решила поделиться и рассказать про свое приключение😅
В общем, подключала сегодня Feign клиента, того самого, который подключается-то за одну аннотацию у людей с прямыми руками😁
Подключаю нужную зависимость, даже убираю транзитивную с уязвимостью, ставлю нужную аннотацию, @EnableFeignClients, завожу интерфейс с нужным клиентом, ставлю над ним аннотацию @FeignClient, прописываю ему имя в скобках и url по которому будет отправлен запрос. Запускаю - ошибка "необходимо указать имя или значение для FeignClient".
Перехожу на свой клиент, перечитываю ещё раз, что у меня написано имя, меняю на value - ошибка та же.
Пошла в гугл, посмотрела разные статьи, документацию, указываешь произвольное имя в скобках аннотации и всё, как говорит amigoscode из YouTube - job done.
Сегодня смотрела его курс по микросервисам, там тоже было подключение Feign клиента, добавила как у него в @EnableFeignClients в скобках basePackage и указала где искать моего клиента. Та же ошибка.
Спрашиваю чат gpt, подсказывает мне подключить другую зависимость дополнительно, попробовала - безрезультатно. Пошла снова в гугл, попробовала разные версии зависимостей, разные дополнительные зависимости. "Нет имени или значения" и все тут.
В один момент, когда игралась с версиями зависимостей подключила несовместимую с Java 11 и ошибка появилась другая и открылось место, где была моя ошибка.
Как бы вы думали, в чем она была?
Оказалось, что я сначала создала клиента для другого сервиса, поставила над ним аннотацию, но не стала настраивать, потому что захотела сначала настроить другой клиент для другого сервиса. И, конечно, же, у него действительно не было ни имени ни значения в параметрах аннотации, ведь я пока не собиралась его использовать.
Ну вот как так можно? 😅
😁5👍2
Всем привет!
Второй день "играю" в девопса. Пытаюсь настроить GitHub Actions. В принципе, у меня уже делается проверка по чекстайлу, плагину spotbugs и проводится обычный билд мавена.
Осталось самое сложное - подключить и запустить тесты постман при пулл реквесте (не зря же я их писала:) ) . Сложность оказалась в том, чтобы собрать докер-композ с 4мя сервисами, rabbitmq, постгрес и liquibase.
Сначала у меня не хотел запускаться liquibase, искала рабочий вариант со вчерашнего вечера. Утром получилось. Потом возникла проблема с Feign клиентом. У меня был захардкожен localhost в параметрах и не сразу получилось заменить на переменную.
Теперь я пытаюсь также побороть rabbitmq. У него также в параметрах конфигурации указан localhost, а в докере для общения между сервисами нужно, чтобы была указана ссылка на сервис, название контейнера, например. Ввести в конфигурацию переменную через конструкцию "${}" почему-то не выходит. Пробую другими путями.
Хочу попробовать с настройкой network в докер-композ, возможно получится. Это какая-то настройка общей сети для всех контейнеров, возможно поможет. Либо буду искать другие варианты.
Потом нужно будет заняться рефакторингом. В понедельник был смешной момент - один из моих методов (калькулятор дистанции между координатами) попал в презентацию лекции по анти-паттернам😅 Вот так вот и переводи сложные формулы с интернета на джава после этого 😁 Придётся теперь узнать, что считается в формуле, которая выдаёт у меня промежуточное значение "а" для вычисления дистанции, через переменную "с". 😂
P.S. Победа!! Сумела засунуть переменную в конфигурацию и переопределила ее в докер-композ! 🥳
Второй день "играю" в девопса. Пытаюсь настроить GitHub Actions. В принципе, у меня уже делается проверка по чекстайлу, плагину spotbugs и проводится обычный билд мавена.
Осталось самое сложное - подключить и запустить тесты постман при пулл реквесте (не зря же я их писала:) ) . Сложность оказалась в том, чтобы собрать докер-композ с 4мя сервисами, rabbitmq, постгрес и liquibase.
Сначала у меня не хотел запускаться liquibase, искала рабочий вариант со вчерашнего вечера. Утром получилось. Потом возникла проблема с Feign клиентом. У меня был захардкожен localhost в параметрах и не сразу получилось заменить на переменную.
Теперь я пытаюсь также побороть rabbitmq. У него также в параметрах конфигурации указан localhost, а в докере для общения между сервисами нужно, чтобы была указана ссылка на сервис, название контейнера, например. Ввести в конфигурацию переменную через конструкцию "${}" почему-то не выходит. Пробую другими путями.
Хочу попробовать с настройкой network в докер-композ, возможно получится. Это какая-то настройка общей сети для всех контейнеров, возможно поможет. Либо буду искать другие варианты.
Потом нужно будет заняться рефакторингом. В понедельник был смешной момент - один из моих методов (калькулятор дистанции между координатами) попал в презентацию лекции по анти-паттернам😅 Вот так вот и переводи сложные формулы с интернета на джава после этого 😁 Придётся теперь узнать, что считается в формуле, которая выдаёт у меня промежуточное значение "а" для вычисления дистанции, через переменную "с". 😂
P.S. Победа!! Сумела засунуть переменную в конфигурацию и переопределила ее в докер-композ! 🥳
🔥9😁1
Всем привет!
Задание на выходные на стажировке у нас было подключить Spring Security по OAuth2 стандарту.
Это такой принцип, при котором существует сервер-шлюз, который перехватывает все запросы, переадресовывает их на сервер аутентификации, который проверяет логин и пароль и, если всё хорошо, выдает токен. С этим токеном, сервер-шлюз перенаправляет запросы на серверы-ресурсы, где хранятся данные пользователей.
Эту тему я ещё изучаю, поэтому не полностью сложилась картина, как это всё работает. Но после последнего задания, стало чуть понятнее.
До этого я как-то с сокурсником обсуждала, как отсеиваются запросы, поступающие напрямую к серверам-ресурсам. Мы подумали, что если ввести адрес напрямую (указать правильный адрес и порт), можно получить доступ к информации без аутентификации.
Такой пример я действительно видела в одном туториале от индуса на ютюбе. Пока он тестировал, он случайно ввёл не тот порт и попал на сервер с ресурсами без какого-либо пароля.
Нам на стажировке дали примерный код для подключения двух дополнительных модулей и, когда у меня уже всё получилось, я убедилась, что напрямую никакого доступа не будет к защищенной информации при правильной настройке.
Нам дали пример с упрощением и я сначала амбициозно подумала, что смогу убрать упрощение и настроить с не заданным пользователем. Когда встретились первые сложности, я ненадолго отложила эту идею до того, как получится по-простому.
Даже с похожим кодом из образца настройка далась не сразу. Но думаю, что обязательно в своем проекте подключу как нужно опираясь на книгу по Security. Временно не получалось ее читать, так и осталось мне 3-4 главы. Но надеюсь скоро всё наладится)
Задание на выходные на стажировке у нас было подключить Spring Security по OAuth2 стандарту.
Это такой принцип, при котором существует сервер-шлюз, который перехватывает все запросы, переадресовывает их на сервер аутентификации, который проверяет логин и пароль и, если всё хорошо, выдает токен. С этим токеном, сервер-шлюз перенаправляет запросы на серверы-ресурсы, где хранятся данные пользователей.
Эту тему я ещё изучаю, поэтому не полностью сложилась картина, как это всё работает. Но после последнего задания, стало чуть понятнее.
До этого я как-то с сокурсником обсуждала, как отсеиваются запросы, поступающие напрямую к серверам-ресурсам. Мы подумали, что если ввести адрес напрямую (указать правильный адрес и порт), можно получить доступ к информации без аутентификации.
Такой пример я действительно видела в одном туториале от индуса на ютюбе. Пока он тестировал, он случайно ввёл не тот порт и попал на сервер с ресурсами без какого-либо пароля.
Нам на стажировке дали примерный код для подключения двух дополнительных модулей и, когда у меня уже всё получилось, я убедилась, что напрямую никакого доступа не будет к защищенной информации при правильной настройке.
Нам дали пример с упрощением и я сначала амбициозно подумала, что смогу убрать упрощение и настроить с не заданным пользователем. Когда встретились первые сложности, я ненадолго отложила эту идею до того, как получится по-простому.
Даже с похожим кодом из образца настройка далась не сразу. Но думаю, что обязательно в своем проекте подключу как нужно опираясь на книгу по Security. Временно не получалось ее читать, так и осталось мне 3-4 главы. Но надеюсь скоро всё наладится)
👍6👏4
Всем привет!
У меня подходит к концу стажировка, вчера было последнее занятие, 7го ноября экзамен и итоговое собеседование будет 13 ноября.
Были интересные сложные задания, в итоге получился большой многомодульный проект, относительно моих предыдущих. Но, конечно, не сравнить с реальными проектами. В нем есть, что дорабатывать, но думается мне поработать над своим клоном курсеры.
Начала не очень давно смотреть курс по микросервисам от Amigoscode, у кого хорошо с английским - советую. Этот курс помог мне с настройкой Feign клиента, RabbitMQ. Дальше по курсу будет переход на кафка и, если не ошибаюсь, kubernetes.
Кстати, немного посмотрела ознакомительное видео на тему kubernetes, увидела что это мощный инструмент, в котором можно сделать так, чтобы было много копий нашего приложения, как бы в изолированных контейнерах. Можно настроить, чтобы в случае, если наше приложение (или база данных) упадет, автоматически запустилась его (ее) копия.
У меня подходит к концу стажировка, вчера было последнее занятие, 7го ноября экзамен и итоговое собеседование будет 13 ноября.
Были интересные сложные задания, в итоге получился большой многомодульный проект, относительно моих предыдущих. Но, конечно, не сравнить с реальными проектами. В нем есть, что дорабатывать, но думается мне поработать над своим клоном курсеры.
Начала не очень давно смотреть курс по микросервисам от Amigoscode, у кого хорошо с английским - советую. Этот курс помог мне с настройкой Feign клиента, RabbitMQ. Дальше по курсу будет переход на кафка и, если не ошибаюсь, kubernetes.
Кстати, немного посмотрела ознакомительное видео на тему kubernetes, увидела что это мощный инструмент, в котором можно сделать так, чтобы было много копий нашего приложения, как бы в изолированных контейнерах. Можно настроить, чтобы в случае, если наше приложение (или база данных) упадет, автоматически запустилась его (ее) копия.
👍8🔥5
Всем привет!
Вчера у меня проходил экзамен на стажировке. Точнее, он начался 7го числа вечером. Нам дали большое задание со сроком выполнения в 24 часа. Нужно было на основе проекта, который мы писали этот месяц, сделать чуть другой проект за сутки.
Одно из первых исправлений было заменить тип идентификатора для главной сущности проекта. Это, естественно, вызвало много исправлений во многих дто, контроллерах, сервисах.
Тут у меня случилось дежавю. Где-то в феврале, когда мы писали 3е ТЗ в Яндекс.Практикуме, моя ревьюер прислала мне после первой проверки задания сообщение в стиле "всё переделать!" У меня было больше 20 замечаний, а проект был, надо сказать, чуть больше калькулятора.
Когда я начала всё тогда исправлять у меня задергался глаз, потому что все классы были подчеркнуты красным, было больше 50 выделенных проблем в Идее и я серьёзно думала, что не пройду дальше того задания.
После тех исправлений мне ревьюер каждый раз присылала замечания и так я привыкла к исправлениям, поэтому в этот раз красные подчеркивания меня не демотивировали. По ходу работы сделала бэкапы с мыслью потом сделать squash коммитов в один, но в итоге, оставила их, на всякий случай, теперь в истории красуются "backup перед security", "плюс 1 backup перед security" и, наконец, "final backup перед security".😁 Но security все-таки пришла в проект, как ее backup не спугивал))
P. S. Давно планирую сделать посты про CORS, CSRF, OAuth2, надеюсь скоро начну потихоньку исполнять задуманное, т.к. планирую это сделать ещё с лета)
P. P. S. Результатов экзамена пока нет)
Вчера у меня проходил экзамен на стажировке. Точнее, он начался 7го числа вечером. Нам дали большое задание со сроком выполнения в 24 часа. Нужно было на основе проекта, который мы писали этот месяц, сделать чуть другой проект за сутки.
Одно из первых исправлений было заменить тип идентификатора для главной сущности проекта. Это, естественно, вызвало много исправлений во многих дто, контроллерах, сервисах.
Тут у меня случилось дежавю. Где-то в феврале, когда мы писали 3е ТЗ в Яндекс.Практикуме, моя ревьюер прислала мне после первой проверки задания сообщение в стиле "всё переделать!" У меня было больше 20 замечаний, а проект был, надо сказать, чуть больше калькулятора.
Когда я начала всё тогда исправлять у меня задергался глаз, потому что все классы были подчеркнуты красным, было больше 50 выделенных проблем в Идее и я серьёзно думала, что не пройду дальше того задания.
После тех исправлений мне ревьюер каждый раз присылала замечания и так я привыкла к исправлениям, поэтому в этот раз красные подчеркивания меня не демотивировали. По ходу работы сделала бэкапы с мыслью потом сделать squash коммитов в один, но в итоге, оставила их, на всякий случай, теперь в истории красуются "backup перед security", "плюс 1 backup перед security" и, наконец, "final backup перед security".😁 Но security все-таки пришла в проект, как ее backup не спугивал))
P. S. Давно планирую сделать посты про CORS, CSRF, OAuth2, надеюсь скоро начну потихоньку исполнять задуманное, т.к. планирую это сделать ещё с лета)
P. P. S. Результатов экзамена пока нет)
❤7👍5🔥2
Всем привет!
Сегодня хочу продолжить своювоображаемую серию постов о Spring Security. Недавно я написала пост, в котором показала, как может выглядеть примерная (и простая) настройка безопасности, с помощью Spring Security.
Когда я первый раз увидела такую настройку, мои первые вопросы были, что такое “csrf().disable()” и что такое “cors().disable()”? Начнем с cors.
Всех больше мне нравится определение из этой статьи:
CORS (Cross-Origin Resource Sharing, англ. «совместное использование ресурсов разных источников») — это стандарт, позволяющий предоставлять веб-страницам доступ к объектам сторонних интернет-ресурсов.
Сторонним считается любой интернет-ресурс, который отличается от запрашиваемого протоколом, доменом или портом.
Например, у нас есть gateway – сервер, принимающий все входящие запросы и переадресовывающий их на разные микросервисы. У этого gateway есть список доверенных источников — порты или адреса, которым разрешен доступ.
Если у нас будут прописаны настройки cors — мы укажем либо аннотациями @CrossOrigin, либо настроем бин CorsWebFilter, — тогда эта информация будет доступна браузеру в заголовках, будет указан HTTP метод и адреса-источники, откуда можно получать/запрашивать данные.
Если у нас не прописаны настройки cors, а в настройках Spring Security не будет указано cors().disable(), то любой запрос с условного localhost:8080 к localhost:9000 будет заблокирован браузером.
Таким образом, настройка “cors().disable()” используется в основном в учебных целях, чтобы не возиться с ошибками доступа, а сфокусироваться на каком-то другом моменте. (я пишу в основном, потому что возможно где-то на рабочих проектах проверку cors тоже отключают, но мне кажется это редкость, хотя я не знаю наверняка).
Сегодня хочу продолжить свою
Когда я первый раз увидела такую настройку, мои первые вопросы были, что такое “csrf().disable()” и что такое “cors().disable()”? Начнем с cors.
Всех больше мне нравится определение из этой статьи:
CORS (Cross-Origin Resource Sharing, англ. «совместное использование ресурсов разных источников») — это стандарт, позволяющий предоставлять веб-страницам доступ к объектам сторонних интернет-ресурсов.
Сторонним считается любой интернет-ресурс, который отличается от запрашиваемого протоколом, доменом или портом.
Например, у нас есть gateway – сервер, принимающий все входящие запросы и переадресовывающий их на разные микросервисы. У этого gateway есть список доверенных источников — порты или адреса, которым разрешен доступ.
Если у нас будут прописаны настройки cors — мы укажем либо аннотациями @CrossOrigin, либо настроем бин CorsWebFilter, — тогда эта информация будет доступна браузеру в заголовках, будет указан HTTP метод и адреса-источники, откуда можно получать/запрашивать данные.
Если у нас не прописаны настройки cors, а в настройках Spring Security не будет указано cors().disable(), то любой запрос с условного localhost:8080 к localhost:9000 будет заблокирован браузером.
Таким образом, настройка “cors().disable()” используется в основном в учебных целях, чтобы не возиться с ошибками доступа, а сфокусироваться на каком-то другом моменте. (я пишу в основном, потому что возможно где-то на рабочих проектах проверку cors тоже отключают, но мне кажется это редкость, хотя я не знаю наверняка).
👍9
Всем привет!
Эта неделя выдалась свободной, всякие ожидания, много свободного времени было. В общем, пошла в интернет, не знаю как, но очутилась на курсе про линукс на степике 😂
Захотелось потренировать навыки работы в терминале. Что-то прошли, всё с нуля, всё просто. Почитала, посмотрела, поделала упражнения, вспомнила, что у меня в избранных лежит непросмотренная видео-серия лекций из Кембриджского университета по терминалу, гит и другим интересным вещам. Первая лекция про терминал и 6-я про гит особенно понравились (остальные ещё не досмотрела). Лекции на английском, но возможно, если поискать, можно найти с переводом.
В начале недели ещё смотрела курс от Amigoscode по микросервисам. Я где-то на середине курса и стало уже немного раздражать, что в курсе, например, 106 видео, но часто эти видео по 2-5 минут. Кажется, что объединил бы в два полных нормальных видео, было бы удобнее. Но что есть, то есть.
В этом курсе, он показывает, как подключить Eureka сервер. У меня есть один пет-проект, туда как раз хочу подключить Eureka, но посмотрела на него (проект) свежим взглядом после стажировки, и что-то так много сделано неправильно, переделать надо бы, что даже подумалось, что с нуля написать будет быстрее 😅 Но попробую переделать в отдельной ветке.
Эта неделя выдалась свободной, всякие ожидания, много свободного времени было. В общем, пошла в интернет, не знаю как, но очутилась на курсе про линукс на степике 😂
Захотелось потренировать навыки работы в терминале. Что-то прошли, всё с нуля, всё просто. Почитала, посмотрела, поделала упражнения, вспомнила, что у меня в избранных лежит непросмотренная видео-серия лекций из Кембриджского университета по терминалу, гит и другим интересным вещам. Первая лекция про терминал и 6-я про гит особенно понравились (остальные ещё не досмотрела). Лекции на английском, но возможно, если поискать, можно найти с переводом.
В начале недели ещё смотрела курс от Amigoscode по микросервисам. Я где-то на середине курса и стало уже немного раздражать, что в курсе, например, 106 видео, но часто эти видео по 2-5 минут. Кажется, что объединил бы в два полных нормальных видео, было бы удобнее. Но что есть, то есть.
В этом курсе, он показывает, как подключить Eureka сервер. У меня есть один пет-проект, туда как раз хочу подключить Eureka, но посмотрела на него (проект) свежим взглядом после стажировки, и что-то так много сделано неправильно, переделать надо бы, что даже подумалось, что с нуля написать будет быстрее 😅 Но попробую переделать в отдельной ветке.
👍9🔥3
Всем привет!
Сегодня расскажу последние новости. Пока я проходила стажировку, мне поступило предложение о работе в другой компании. Я прошла туда собеседование, выполнила тестовое задание и продолжала выполнять задания со стажировки.
Так вышло, что в последний день стажировки нам сказали, что до конца месяца они не будут принимать решение, либо решение принято, но по другим причинам не будет сказано раньше. А на следующий день мне пришел хороший оффер в другую компанию.
Я его приняла и у меня был первый рабочий день в прошлый четверг. Сначала я побоялась об этом написать, потому что вдруг меня уволят в первый же день. 😂 Но ничего такого не произошло, тут хороший онбординг процесс, я уже начинаю верить, что всё происходит в реальности и мне не приснилось. 😅
В связи с этими своими мыслями, вспомнила историю одного сеньёра об одном своем помощнике - джуне, который только через месяц работы немного успокоился и перестал бояться, что его уволят не сегодня / завтра. 😁
Сегодня расскажу последние новости. Пока я проходила стажировку, мне поступило предложение о работе в другой компании. Я прошла туда собеседование, выполнила тестовое задание и продолжала выполнять задания со стажировки.
Так вышло, что в последний день стажировки нам сказали, что до конца месяца они не будут принимать решение, либо решение принято, но по другим причинам не будет сказано раньше. А на следующий день мне пришел хороший оффер в другую компанию.
Я его приняла и у меня был первый рабочий день в прошлый четверг. Сначала я побоялась об этом написать, потому что вдруг меня уволят в первый же день. 😂 Но ничего такого не произошло, тут хороший онбординг процесс, я уже начинаю верить, что всё происходит в реальности и мне не приснилось. 😅
В связи с этими своими мыслями, вспомнила историю одного сеньёра об одном своем помощнике - джуне, который только через месяц работы немного успокоился и перестал бояться, что его уволят не сегодня / завтра. 😁
🔥17❤1
Всем привет!
Подумала, что не рассказала еще здесь о своем небольшом приключении на выходных. Началось все с того, что в первый свой рабочий день, у меня на компьютере вылез «экран-смерти». Самое время, подумала я, умереть компьютеру. (Рабочий мне еще не пришел)
Сначала запустила по гайду из интернета команду, сканирующую и восстанавливающую поврежденные файлы системы. Думала, может поможет. Но в субботу снова он — синий экран с грустным смайлом и сообщением, что пора тебе покупать новый компьютер.
Решила попробовать откатить состояние к заводским настройкам, без удаления личных данных. Но на всякий случай сделала бэкап. В воскресенье запустила процесс. Посмотрела на список удаленных программ, вспомнила, что надо заново же и базу данных теперь устанавливать, да git, да докер. Немного было пала духом, но решила постепенно восстановить. Большую часть программ решила не устанавливать. Всякие Dbeaver и Insomnia, которые устанавливали во время курса в практикуме.
В общем, восстановление прошло пока в основном безболезненно. Данные не потеряла. По причине «экрана» думаю на докер, что когда устанавливала его весной, сделала не всё правильно. Тут когда на стажировке запускала в нем 7 образов одновременно, через докер-композ, он часто зависал, отказывался работать, запускаться, закрываться. В этот раз, когда устанавливала, сделала более внимательно по документации. Надеюсь, что все будет работать нормально. Завтра-послезавтра потестирую его как следует :)
Подумала, что не рассказала еще здесь о своем небольшом приключении на выходных. Началось все с того, что в первый свой рабочий день, у меня на компьютере вылез «экран-смерти». Самое время, подумала я, умереть компьютеру. (Рабочий мне еще не пришел)
Сначала запустила по гайду из интернета команду, сканирующую и восстанавливающую поврежденные файлы системы. Думала, может поможет. Но в субботу снова он — синий экран с грустным смайлом и сообщением, что пора тебе покупать новый компьютер.
Решила попробовать откатить состояние к заводским настройкам, без удаления личных данных. Но на всякий случай сделала бэкап. В воскресенье запустила процесс. Посмотрела на список удаленных программ, вспомнила, что надо заново же и базу данных теперь устанавливать, да git, да докер. Немного было пала духом, но решила постепенно восстановить. Большую часть программ решила не устанавливать. Всякие Dbeaver и Insomnia, которые устанавливали во время курса в практикуме.
В общем, восстановление прошло пока в основном безболезненно. Данные не потеряла. По причине «экрана» думаю на докер, что когда устанавливала его весной, сделала не всё правильно. Тут когда на стажировке запускала в нем 7 образов одновременно, через докер-композ, он часто зависал, отказывался работать, запускаться, закрываться. В этот раз, когда устанавливала, сделала более внимательно по документации. Надеюсь, что все будет работать нормально. Завтра-послезавтра потестирую его как следует :)
👍10
Всем привет!
В среду посмотрела интересный митап. Особенно понравился второй доклад на тему «Приложение от проекта до релиза: этапы реализации».
Всего было три доклада, но, честно говоря, мне не хватает пока знаний для первого и третьего докладов. В первом было про BeanPostProcessor-ы, там очень хитрую инициализацию объектов докладчики провернули, что по ощущениям, в комментариях чата очень мало, кто понял как и зачем они это сделали. А в третьем докладе была тема «JMX (Java Management Extension) в 2023». Это протокол мониторинга и менеджмента для JVM (из описания).
Во втором докладе было про последовательность этапов разработки на старте проекта и про реализации новых фич, про архитектуру в целом. Очень бодрый доклад, интересная дискуссия после него. Рекомендую посмотреть, кому интересно.
В среду посмотрела интересный митап. Особенно понравился второй доклад на тему «Приложение от проекта до релиза: этапы реализации».
Всего было три доклада, но, честно говоря, мне не хватает пока знаний для первого и третьего докладов. В первом было про BeanPostProcessor-ы, там очень хитрую инициализацию объектов докладчики провернули, что по ощущениям, в комментариях чата очень мало, кто понял как и зачем они это сделали. А в третьем докладе была тема «JMX (Java Management Extension) в 2023». Это протокол мониторинга и менеджмента для JVM (из описания).
Во втором докладе было про последовательность этапов разработки на старте проекта и про реализации новых фич, про архитектуру в целом. Очень бодрый доклад, интересная дискуссия после него. Рекомендую посмотреть, кому интересно.
YouTube
Sber Java Meetup: Избегая техдолга
Подробнее о Java-конференциях:
— весной — JPoint: https://jrg.su/gTrwHx
— осенью — Joker: https://jrg.su/h7yvG4
— —
*«Да (не) инициализируйся ты уже!»*
Как легко разработать DSL для Spring? Правильно – никак! Михаил Сильванович, Максим Шестаков, Евгений Зубенко…
— весной — JPoint: https://jrg.su/gTrwHx
— осенью — Joker: https://jrg.su/h7yvG4
— —
*«Да (не) инициализируйся ты уже!»*
Как легко разработать DSL для Spring? Правильно – никак! Михаил Сильванович, Максим Шестаков, Евгений Зубенко…
🔥7👍1
Всем привет!
Вчера интересовалась дженериками. В одной статье на хабре в комментариях попалась ссылка на интересное видео по дженерикам. В нем доклад от 2016 года с конференции JPoint. Очень понравился, до этого не знала разницу между записями <? extends Number> от <? super Number>.
Докладчик рассказал, что однажды задал вопрос, что можно добавить в такой список:
А что можно добавить в такой список:
В обоих случаях, правильно ответили 15% людей, я до его объяснения также ответила неправильно. Мне казалось, что в первый список можно положить любой тип, который наследуется от Number, а во второй список - Object и Number.
А оказалось, что правильный ответ был, что в первый список безопасно можно положить только null, а во второй список можно положить любой тип, который наследуется от Number, но нельзя класть обычный Object.
Если кто-то как и я не знал этого, советую послушать объяснение почему в этом видео, докладчик отлично объясняет на понятных примерах.
После этого видео, стала смотреть другие видео на канале и узнала еще много интересного про Pageable, оказывается он бьет по перформансу, если его неправильно использовать.
Потом, на том же канале, мне попалось видео по компетенциям и грейдам IT-специалистов и меня порадовало, что из графы сеньера мне осталось только научиться работать с ExecutorService и дело, как говорится, в шляпе 😁
Вчера интересовалась дженериками. В одной статье на хабре в комментариях попалась ссылка на интересное видео по дженерикам. В нем доклад от 2016 года с конференции JPoint. Очень понравился, до этого не знала разницу между записями <? extends Number> от <? super Number>.
Докладчик рассказал, что однажды задал вопрос, что можно добавить в такой список:
List<? extends Number> numbers = new ArrayList<>();
А что можно добавить в такой список:
List<? super Number> numbers = new ArrayList<Object>();
В обоих случаях, правильно ответили 15% людей, я до его объяснения также ответила неправильно. Мне казалось, что в первый список можно положить любой тип, который наследуется от Number, а во второй список - Object и Number.
А оказалось, что правильный ответ был, что в первый список безопасно можно положить только null, а во второй список можно положить любой тип, который наследуется от Number, но нельзя класть обычный Object.
Если кто-то как и я не знал этого, советую послушать объяснение почему в этом видео, докладчик отлично объясняет на понятных примерах.
После этого видео, стала смотреть другие видео на канале и узнала еще много интересного про Pageable, оказывается он бьет по перформансу, если его неправильно использовать.
Потом, на том же канале, мне попалось видео по компетенциям и грейдам IT-специалистов и меня порадовало, что из графы сеньера мне осталось только научиться работать с ExecutorService и дело, как говорится, в шляпе 😁
🔥11
Всем привет!
На днях занималась подключением Liquibase в одном из своих проектов и запуском ее с базой данных в docker-compose. Снова, как и в первый раз на стажировке, у меня возникли сложности с этим. Информации в интернете не так и много на эту тему (мне мало попадалось). Поэтому я решила написать здесь небольшой гайд на эту тему.
Дисклеймер: Последний раз, когда подключала, узнала, что можно настроить Dockerfile для ликвибейз отдельно, в котором будут прописаны и команды, а в docker-compose уже запускать билд. Я пока не настраивала Dockerfile и все еще не знаю, как делать правильно — с ним или без него. Поэтому гайд не гайд, а орел.
Итак, гайд для многомодульного проекта, где ликвибейз подключается в отдельном модуле. Кратко о подключении: я делала в Maven, поэтому в pom.xml добавила необходимую зависимость для ликвибейз (liquibase-core), а также мавен-плагин (liquibase-maven-plugin), в котором прописала путь к файлу с настройками ликвибейз (тег propertyFile) и путь к главному файлу ченджлогов, в котором прописаны пути к мелким ченджлогам, (тег changeLogFile). После этого завела liquibase.properties, в котором также прописала путь к мастер ченджлогу (если все лежит по пути, который предлагается в документации по умолчанию, то там и будет происходить поиск мастер ченджлога).
Итак, docker-compose. Сначала настраиваем базу данных, ей обязательно добавляем healthcheck. Для постгрес я делала такой:
Далее добавляем ликвибейз и прописываем условие, после которого он начинает свою работу — наша база данных здорова и может принимать запросы:
Если docker-compose файл лежит в отдельной папке, то путь к файлу нужно начать с двух точек, чтобы подняться на папку вверх. Далее, после этой настройки, можно добавить в docker-compose наш микросервис, добавив условие для запуска — ликвибейз успешно завершила работу:
P.S.: чтобы все остальные ченджлоги были найдены ликвибейз, необходимо в мастер файле добавить условие relativeToChangelogFile: true в yaml, либо relativeToChangelogFile="true" в xml формате.
На днях занималась подключением Liquibase в одном из своих проектов и запуском ее с базой данных в docker-compose. Снова, как и в первый раз на стажировке, у меня возникли сложности с этим. Информации в интернете не так и много на эту тему (мне мало попадалось). Поэтому я решила написать здесь небольшой гайд на эту тему.
Дисклеймер: Последний раз, когда подключала, узнала, что можно настроить Dockerfile для ликвибейз отдельно, в котором будут прописаны и команды, а в docker-compose уже запускать билд. Я пока не настраивала Dockerfile и все еще не знаю, как делать правильно — с ним или без него. Поэтому гайд не гайд, а орел.
Итак, гайд для многомодульного проекта, где ликвибейз подключается в отдельном модуле. Кратко о подключении: я делала в Maven, поэтому в pom.xml добавила необходимую зависимость для ликвибейз (liquibase-core), а также мавен-плагин (liquibase-maven-plugin), в котором прописала путь к файлу с настройками ликвибейз (тег propertyFile) и путь к главному файлу ченджлогов, в котором прописаны пути к мелким ченджлогам, (тег changeLogFile). После этого завела liquibase.properties, в котором также прописала путь к мастер ченджлогу (если все лежит по пути, который предлагается в документации по умолчанию, то там и будет происходить поиск мастер ченджлога).
Итак, docker-compose. Сначала настраиваем базу данных, ей обязательно добавляем healthcheck. Для постгрес я делала такой:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U названиеБД"]
interval: 10s
timeout: 5s
retries: 3
Далее добавляем ликвибейз и прописываем условие, после которого он начинает свою работу — наша база данных здорова и может принимать запросы:
liquibase:
image: liquibase/liquibase:4.19.1 #(есть и более новые версии)
container_name: liquibase
depends_on:
db: #(наименование сервиса БД из docker-compose)
condition: service_healthy
command:
- --url=jdbc:postgresql://db:5432/названиеБД?user=имяПользователя&password=пароль
- --changeLogFile=master.xml # master.yaml, расширение не влияет
- update
volumes:
# если мастер ченджлог лежит отдельно, то делаются две папки volumes, если мастер лежит в одной папке с остальными ченджлогами, то достаточно скопировать одну папку, где все лежит, иначе мастер файл задублируется и ликвибейз упадет с ошибкой.
- ./модуль с ликвибейз/src/main/resources/db/master.xml:/liquibase/master.xml
- ./модуль с ликвибейз/src/main/resources/db/changelog:/liquibase/changelog
Если docker-compose файл лежит в отдельной папке, то путь к файлу нужно начать с двух точек, чтобы подняться на папку вверх. Далее, после этой настройки, можно добавить в docker-compose наш микросервис, добавив условие для запуска — ликвибейз успешно завершила работу:
depends_on:
liquibase:
condition: service_completed_successfully
P.S.: чтобы все остальные ченджлоги были найдены ликвибейз, необходимо в мастер файле добавить условие relativeToChangelogFile: true в yaml, либо relativeToChangelogFile="true" в xml формате.
👍8❤1
Всем привет!
Сегодня знаменательный день в моём календаре - у меня сегодня день рождения 🥳
Я бы сказала, что мне исполнилось 18 лет, но в самом первом посте уже проспойлерила, что мне "после 30-ти"😅
Интересно, что первый спринт в Яндекс.Практикуме начался у меня тоже 5 декабря, в день рождения, год назад. Очень здорово, что в этот день рождения я уже получаю поздравления от коллег в новой профессии.
Также, спасибо всем вам, что подписались, поддерживаете реакциями и/или комментариями, это очень мотивирует! Если мне удается кого-то из вас также мотивировать, то это большая радость для меня 🤗
Сегодня знаменательный день в моём календаре - у меня сегодня день рождения 🥳
Я бы сказала, что мне исполнилось 18 лет, но в самом первом посте уже проспойлерила, что мне "после 30-ти"😅
Интересно, что первый спринт в Яндекс.Практикуме начался у меня тоже 5 декабря, в день рождения, год назад. Очень здорово, что в этот день рождения я уже получаю поздравления от коллег в новой профессии.
Также, спасибо всем вам, что подписались, поддерживаете реакциями и/или комментариями, это очень мотивирует! Если мне удается кого-то из вас также мотивировать, то это большая радость для меня 🤗
🎉17❤3🔥2👏1