Тру-Джава
137 subscribers
31 photos
79 links
блог начинающего Java-программиста

Чат: https://t.me/trujavachat
Download Telegram
Всем привет!

Сегодня будет небольшой апдейт. На прошлой неделе немного выпала из жизни - писала диплом. Вчера отправила на проверку 2 этап. Когда зачтут, останется только добавить свою фичу небольшую и готово.

Думаю буду делать рейтинг событий с лайками, дизлайками и общей 5 звездочной оценкой. По заданию нужно будет самой написать Postman тесты - это будет новый опыт для меня. До этого тестировала там сама свои проекты вручную, проверяя разные запросы на разные эндпоинты, потом уже писала юнит и интеграционные тесты.

Стала потихоньку возвращаться к книжкам, курсу на степике. Сейчас у меня одновременно начато очень много книг, поэтому решила читать по очереди, чтобы не разрываться. Первая в очереди Spring Security in Action, очень стала интересна тема безопасности, столько в ней есть нюансов, что хочется в этом разбираться.

Потом думаю буду дочитывать Kafka в действии и Spring Паттерны. Сегодня попалось в каком-то чате, что есть Kafka Security (streams security) - захотелось посмотреть, почитать.

Но всё сразу читать не получается, буду стараться сохранять очередность))
🔥7👍2
Всем привет!

На днях в Практикуме был вебинар с нашим наставником группы. Его спросили про JPA и Null параметры. Он предложил вариант сделать дерево условий, если этот пришедший параметр null, то не передавать его в метод репозитория.

Самое интересное, что в нашем случае приходило 7 null параметров в одном из тестов. Кажется, что это 7 условий. Но что если приходит 5 параметров null, а остальные не null? Это дополнительное условие, потому что нет колонок со значением null в нашей таблице событий. Когда я делала этот эндпоинт, я прикинула, что это (минимум) 21 вариация. 14 if-else условий проверки на null на каждый параметр, плюс варианты, когда первые два null, а остальные не null, первый и третий null, а остальные не null. В этом духе.

Естественно, этот момент предусмотрен в Spring Data JPA. Подробнее можно посмотреть в этой статье. Я выпишу пример с коротким объяснением из этой статьи:

@Query("SELECT c FROM Customer c WHERE (:name is null or c.name = :name) and (:email is null or c.email = :email)") 
List<Customer> findCustomerByNameAndEmail(@Param("name") String name, @Param("email") String email);

В этом случае, если параметр name будет null, условие будет верно всегда и не повлияет на выборку WHERE. По поводу конструкции @Param("name"), в моем случае работало и без нее.

Может кому пригодится, если вдруг кто не знал про это.
👍11🔥1
Всем привет!

C 19 сентября из каждого (утюга) java канала сообщалось про выход новой версии java 21. А мой канал что? Не утюг? 😅 На самом деле, расписывать новшества я не буду, потому что они уже много где были хорошо описаны, например, я читала, кроме документации, эту статью.

Диплом мне сегодня зачли, поэтому самое время начать вплотную знакомиться с новой версией джава. Меня привлекло, что в новой версии в switch кейсах, наконец, можно будет добавлять условие, с помощью ключевого слова when:

case Integer i when i > 0 -> String.format("positive int %d", i); 


Я такую возможность захотела в первый день, когда впервые экспериментировала со switch конструкцией в прошлом году. Единственное, смущает, что новый паттерн-матчинг имеет ограничения, например, что кейсы должны быть исчерпывающими. Но в этом плане я еще не до конца разобралась, сегодня только пришла идея поэкспериментировать с нововведениями.

Еще из новостей, во вторник у меня было собеседование на стажировку в нашем городе. Результаты будут только на следующей неделе. Вопросы были очень легкими, в стиле, что такое класс Object, какие у него есть методы? Чем отличается ArrayList от LinkedList? Как, вкратце, устроена HashMap? Чем отличается аннотация @Controller от @RestController? Зачем ставить аннотацию @Repository? Такого рода вопросы.
🔥5😁2
Самое главное, ради чего писался пост, забыла написать 😁:

Презентацию новой версии я частично смотрела онлайн. Приободрило, как начинающего разработчика, когда у троих опытных разработчиков Oracle не получилось запустить видео со звуком. Минут 5 они возились и говорили разные приободряющие слова, в стиле: «Мы разработчики, нам свойственно ошибаться. Но мы не сдаемся, пока не победим»💪
😁8
Всем привет!

Хочу рассказать о том, что поняла только на днях (к своему стыду). Первый звонок, что что-то здесь не так, прозвучал, когда писала пост про null параметры. Сначала я написала, что это JPA Hibernate, потом перечитала начало статьи и увидела, что это Spring Data JPA, исправила.

Потом посмотрела видео про паттерны в Spring, Евгения Борисова, услышала ещё раз про Spring Data, второй звонок.

Вчера начала читать книгу про Hibernate (идея с чтением книг последовательно, окончательно провалилась) и паззл в голове сложился.

Есть 3 отдельных понятия: JPA, Native Hibernate, Spring Data JPA.

Как я думала до этого? Что есть спецификация JPA со стандартами, есть ORM фреймворк для выполнения этих стандартов, один из таких Hibernate. И есть где-то Spring Data, которая что-то где-то делает, где и что я не знала.

Так вот оказывается Spring Data JPA делала много чего у меня прямо под носом: делала реализацию моих запросных методов (findByNameAndEmail), бин-реализацию для моих интерфейсов-репозиториев, которые наследовались от JpaRepository, и избавляла меня от написания повторяющегося кода.

Сейчас я точно вспоминаю, что нам про это рассказывалось в теории в Практикуме, но в тот момент в голове по полкам не разложилось. Лучше поздно, чем никогда 😅
👍5🔥1
Всем привет!

Есть ли жизнь после Практикума?🤪 Когда долго ждешь окончания чего-нибудь, и это на самом деле заканчивается, становится немного пусто, появляются мысли: "И что теперь?"

В пятницу я неофициально закончила курсы "Java-разработчика" в Яндекс.Практикум (официальное окончание будет 14 октября). Получается надо редактировать свой вступительный пост здесь.🤭 Но глобально, что же делать дальше?

Когда была система спринтов и я раньше времени что-то заканчивала, четко знала, что будет дальше в программе (в общих чертах), знала что всегда будет какой-то проект, задачки/тесты. А тут появилась неуверенность в "завтрашней программе".

Поэтому пошла искать себе такую программу. Посмотрела разные пути развития (roadmap), требования из нескольких вакансий, и наметила себе посмотреть Elasticsearch, GraphQL, MongoDB и, возможно, Kubernetes.

Нашла классный туториал по первому здесь, по второму здесь, а по MongoDB недавно скачала классную книжку (MongoDb for Jobseekers).

Также ещё нашла интересный репозиторий на гитхаб с полезными ссылками, awesome java, и там нашла интересную вещь, как game development engines для разработки игр на java. Я давно сыну обещала сделать игру для него в стиле его любимой игры, думаю попробовать jMonkeyEngine.

Посчитала, из относительно крупных учебных проектов у меня накопилось 4 учебных, и 4 своих (2 из них появились благодаря интересным тестовым заданиям). Был у меня репозиторий сфоркнутый с тестовыми заданиями, думала взять какую-нибудь идею в разработку, но в основном проекты там мелкие, в стиле "простой калькулятор", игра, где смысл показать, что ты умеешь в наследование.

Поэтому отфоркнула этот репозиторий, добавила в свой блог-проект создание постов с ролью авторов (method security), и, отложив его пока, решила разнообразить свое портфолио ещё и игрой на java. В блог можно, конечно, добавить рейтинг, комментарии, но это всё выглядит в принципе не очень сложно, несколько раз реализовывала похожий и такой же функционал и совсем недавно, поэтому решила пока переключиться и попробовать сделать что-то совсем другое (дополнительно к туториалам выше).👨‍💻
👍81
Всем привет!

Я прошла на стажировку! Точнее, я прошла на две стажировки, но одна из них была в Астон, где очень жесткие условия. Поэтому туда я отказалась идти. На прошлой неделе у меня было собеседование на другую стажировку с возможностью дальнейшего трудоустройства в их компанию. Вчера пришел результат, что я прошла, начало будет 2 октября. Поделюсь впечатлениями, как начнется.

Вчера еще вспомнила про курс для миддлов со степика. Еще раз захотелось его порекомендовать, он бесплатный. Там многие вещи пересекаются с курса Я.Практикума для джунов, но чем мне нравится — деталями по темам. Курс, видимо, создан был Семеном Кирековым, потому что его вебинары на курсе самые крутые и полезные и ссылки на «почитать подробнее на тему» ведут на его блог. Правда, пишет он там на английском, поэтому подойдет не всем. Но на степике теоретические статьи на русском.

На моем собеседовании по Spring и Hibernate, собеседующий спросил меня, как правильно создавать базы для приложения. Я наивно ответила, что нужно создавать файл schema.sql. Он сказал: «Нет, есть способ лучше». Но какой не сказал. Тут на курсе, нашла ответ — нужно делать, так называемые, миграции. В курсе рассказывается про инструмент миграции Liquibase, приведены примеры как, объяснено почему.

Еще интересная вещь, которую я сегодня там прочитала — объяснение, что это за такое предупреждение, которое у нас всегда выходило в учебных проектах, помню даже ответ наставника, мол, не заморачивайтесь. Вот так выглядит это предупреждение:

2022-04-13 23:01:34.863  WARN 109326 --- [main] JpaBaseConfiguration$JpaWebConfiguration : 
spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering.
Explicitly configure spring.jpa.open-in-view to disable this warning

Оказывается, это антипаттерн с названием Open Session in View. Он сделан для обхода исключения LazyInitializationException, которое бросает Hibernate, когда ему необходимо инициализировать связанную сущность, для которой указана «ленивая» загрузка, но при этом отсутствует контекст сессии Hibernate (попросту говоря, когда мы запросили сущность из базы без дополнительных полей — сущностей хранящихся в других таблицах, а потом обратились к этим полям, по типу event.getCategories() или book.getGenres()).

«Суть данного антипаттерна в том, что сессия Hibernate открывается и закрывается не в сервисном слое, а в слое "выше" - на уровне представления (view layer), к примеру в контроллере. Контроллер вызывает сервисный слой, который выполняет различные действия с данными и возвращает управление контроллеру. А поскольку сессия всё ещё открыта, слой представления может инициализировать объекты, для которых указана "ленивая" загрузка. Однако если сервисный слой выполнит commit, то транзакция завершится. Из-за этого Hibernate будет выполнять все SQL-запросы, инициированные на слое представления, в режиме auto-commit, то есть каждый такой SQL-запрос будет выполняться в отдельной транзакции, что приведёт к повышению нагрузки на БД, т.к. в конце каждой транзакции БД должна сделать запись в журнале транзакций на диске, что является ресурсозатратной операцией.

Помимо повышения нагрузки на БД у Open Session In View есть и другой недостаток. Поскольку операции выполняются не в одной транзакции, а в двух и более, можно получить неконсистентное состояние данных. Spring Boot по умолчанию использует Open Session in View.» Чтобы это отключить, нужно установить false параметру spring.jpa.open-in-view в application.properties.
6🔥6👏4👍1
Всем привет!

Хочу рассказать об интересной вещи, которую узнала вчера-позавчера. Начну немного издалека. Не очень давно, на последнем моем занятии на интенсиве, мы обсуждали Hibernate и кто-то задал вопрос: "почему считается, что 'жадная' выборка данных (fetch eager) не решает проблему n + 1? Казалось бы, не для этого ли ее придумали?"

Вкратце напомню, что это за проблема "n + 1". Она часто возникает, когда мы обращаемся к какой-то сущности, например, книге, которая имеет связь с другой сущностью, например, жанром. У одной книги может быть несколько жанров, и у одного жанра может быть несколько книг. Такая связь называется многие-ко-многим и по умолчанию в Hibernate для нее выполняется ленивая загрузка (fetch lazy).

Таким образом, если мы запросим список книг из репозитория, Hibernate сгенерирует один запрос. Если мы захотим пройтись по жанрам книг в цикле, в каких-нибудь статистических, фильтрующих или других целях, из-за того, что загрузка жанров ленивая, то есть данные запрашиваются только тогда, когда они нужны, для каждой книги Hibernate сделает дополнительный запрос в базу данных, чтобы получить жанры этой книги.


List<Book> books = bookRepository.findAll();
for (Book book : books) {
List<Genre> genres = book.getGenres();
// делаем что-то с жанрами
}


Что делает Hibernate, если указать параметр fetch EAGER? Он генерирует дополнительные запросы сразу, до обращения к жанрам, поэтому EAGER не решает проблемы n + 1!

Это я узнала буквально пару дней назад и это меня очень поразило🤓

P. S. Это не решение проблемы n + 1, это объяснение почему FETCH EAGER не решает эту проблему. О решениях будет отдельный пост позже 🤗
👍101
Всем привет!

Вчера у меня началась классная стажировка. Было первое занятие, познакомились, наметили план работы. Впечатления отличные.

Будем разрабатывать интересный проект. Он будет включать в себя 6 микросервисов (плюс минус). В проекте будет использоваться Liquibase, Spring Security, RabbitMQ (возможно аналог), будут push-уведомления, обращения к внешним сервисам. В общем, очень близко к настоящему взрослому проекту. Будут допущены некоторые упрощения в учебных целях, но для меня это будет самый большой проект, пока что.

Liquibase, кстати, начала тестировать в выходные. Решила сделать проект из курса для миддлов (до этого планировала переключиться на разработку игры на jMonkeyEngine и что-то пока ничего из этого не вышло, даже не знаю с чего там начать).

С Liquibase не сразу получилось, я ещё включила у Hibernate настройку для ddl-auto на validate, по совету с курса, чтобы была проверка на соответствие сущностей и реальной базы. Учитывая, что первый раз делала базы через Liquibase, проект у меня очень долго не заводился, но было интересно. В конце концов получилось, думаю в свободное время буду продолжать его делать, пока не началась активная разработка нового проекта.
👍8👏2
Всем привет!

Смотрела вчера лекцию по API безопасности. Там говорилось о последних стандартах PCI DSS 4.0*, которые должны применить у себя компании до 1 квартала 2024 года.

Вкратце расскажу несколько моментов, что было сказано в видео:

1. Количество API растёт, в прогнозах ещё больше будет рост, в силу удобства подхода.

2. Часто делают проверки безопасности на уровне клиента (браузера, например) - делают невидимыми различные кнопки пользователям без доступа к таким ресурсам, к примеру. В этом случае злоумышленники, если найдут верный эндпоинт, могут напрямую получить доступ к данным (отправив прямой запрос на эндпоинт), если нет дополнительных проверок для API.

3. Одной из хороших практик была названа практика Security Gateway, специальный сервис, ответственность которого аутентифицировать и авторизовывать пользователей.

Сразу же загорелась попробовать реализовать такой сервис в последнем проекте с миддл курса. Если следовать их ТЗ, там тоже есть упрощения, которые я хочу усложнить для себя и попробовать сделать ближе к тому, как надо. Поэтому этот проект превращается в мой пет, потому что я меняю для себя требования, как должно работать. Тем более, что начала писать на хайпе на Java 21 (может я увидела хайп там, где его нет, конечно 😅) и на последней стабильной версии Spring Boot. Там настройка Spring Security немного отличается.

Осталось дело за малым, найти как это правильно сделать 😅, нашла пока статью с 7 вариантами, буду что-нибудь из этого пробовать)

P. S. Кстати, не говорила вроде бы, что этот проект - клон учебного сайта Coursera (на минималках).

*Стандарт PCI DSS — это международный стандарт безопасности, созданный специально для защиты данных платежных карт.
👍81
Всем привет!

Вернемся к проблеме “n + 1”, о которой я недавно делала пост. Там я рассказала об одном соблазнительном, но неправильном решении. Кстати сказать, один раз я применила его летом в одном из ТЗ Я.Практикума. Тогда мне ревьюер интересно ответила, что раньше бы она сказала на fetch eager, что это 100% нельзя использовать, но сейчас у них тимлид заставляет всех использовать fetch eager на проекте. То есть можно представить, какая нагрузка идет на базу данных, когда ВСЕ запросы идут, как n + 1, правда?

Какие есть правильные решения?

1. Использовать JOIN FETCH в аннотации @Query:

    @Query(value = "" +
"SELECT c FROM Course c " +
" JOIN FETCH c.lessons")
List<Course> findAll();

2. Использовать аннотацию @EntityGraph над методом в репозитории:

@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, осталось до конца совсем немного, потом буду смотреть в документации замены для устаревших методов (на выходных научилась это искать там) и буду дописывать свою курсэру (тру-сэру? или, может, трус-курс? 🤣).
🔥6😁2👍1
Всем привет!

Как-то писала, что реализовывала Spring Security с дополнительным фильтром на JWT, но не написала, что такое JWT.

Хочу сегодня это исправить 👨‍💻 Для тех, кто не знает, надеюсь будет интересно, а кто знает, надеюсь, поправит меня, если я где-то ошибусь 😊

Итак, как вообще расшифровывается JWT? Расшифровывается, как JSON Web Token.

Как он выглядит?

Примерно, вот так (новые строчки добавлены для удобства чтения):

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

Это своего рода закодированное сообщение. По условному разделению по строкам, верхняя строка означает заголовок, в нем может быть указано при помощи какого алгоритма выполняется хеширование подписи. Посередине — полезная информация, в ней может находиться username, id и/или роли пользователя, или что-то другое, что мы захотим добавить. А третья часть — это подпись, которая кодируется при помощи секретного ключа.

Каждая часть кодируется отдельно при помощи алгоритма base64url, соединяется через точку и хешируется при помощи алгоритма из заголовка, выглядит это так:

HMACSHA256(
base64UrlEncode(заголовок/header) + "." +
base64UrlEncode(полезная инфа/payload),
наш-256-битный-секрет
)


На официальном сайте, можно попробовать создать свой JWT. Если изменить хоть один символ в токене, то уже не пройдет проверку на соответствие на сервере.

Что нужно иметь в виду еще. Нужно на сервере обязательно проверять весь токен полностью, не только, условно, хедер. Например, прочитала в официальной брошюре-книге, что злоумышленник может указать в заголовке, что, мол, токен без подписи, пропускай мой запрос.

Поэтому, если мы хотим сохранить безопасность доступа, нужно проверять токен полностью, вместе с подписью, а также лучше делать его коротким по продолжительности жизни. В этом случае, как прочитала в комментариях у этой статьи про JWT на хабре, можно организовать автообновление токена с помощью oAuth2. До oAuth2 я еще пока не дошла, поэтому пока как на деле это сделать не знаю.
🔥4👍1
Всем привет!)

О мотивации пост.

Вчера пришла мысль, что меня очень мотивирует в изучении java и всего, что с ней связано (где-то о java говорят в мужском роде, мне почему-то хочется говорить в женском, надеюсь это вкусовщина, а не моя ошибка 😅).

Мысль меня посетила после лекции, которая закончилась уже вечером, а мне сильно захотелось заняться программированием и прямо так, чуть ли не всю ночь кодить. Задалась вопросом и поняла, что меня очень мотивируют крутые специалисты. Когда смотрю, как они программируют или рассказывают о чем-то в чем хорошо разбираются - это меня завораживает.

Один раз был смешной случай, как-то случайно по ссылке посмотрела час лекции по математике, там были сложные вычисления, что-то из продвинутого уровня, ничего не поняла, но не могла отвести взгляда)) после этого записалась на этот курс (бесплатный), но к сожалению не мой уровень.

Пыталась было с попроще видео на ютюбе зайти, но всё равно не вышло и решила не отвлекаться пока от программирования. Когда-нибудь возможно вернусь ещё)

А вас что мотивирует? 😊
🔥5
Всем привет!

Хочу сегодня поделиться впечатлениями со стажировки. У нас выстраивается интересный большой проект. Пока там 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.

Кстати, в книжке недавно прочитала такое наставление для новичков, сейчас уместно, как никогда об этом рассказать - "никогда не используйте в коде что-то, когда не знаете наверняка, что это делает и как работает" 😊
👍8
Всем привет!

Меня вчера почти победил 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 и ошибка появилась другая и открылось место, где была моя ошибка.

Как бы вы думали, в чем она была?

Оказалось, что я сначала создала клиента для другого сервиса, поставила над ним аннотацию, но не стала настраивать, потому что захотела сначала настроить другой клиент для другого сервиса. И, конечно, же, у него действительно не было ни имени ни значения в параметрах аннотации, ведь я пока не собиралась его использовать.

Ну вот как так можно? 😅
😁5👍2
Всем привет!

Второй день "играю" в девопса. Пытаюсь настроить GitHub Actions. В принципе, у меня уже делается проверка по чекстайлу, плагину spotbugs и проводится обычный билд мавена.

Осталось самое сложное - подключить и запустить тесты постман при пулл реквесте (не зря же я их писала:) ) . Сложность оказалась в том, чтобы собрать докер-композ с 4мя сервисами, rabbitmq, постгрес и liquibase.

Сначала у меня не хотел запускаться liquibase, искала рабочий вариант со вчерашнего вечера. Утром получилось. Потом возникла проблема с Feign клиентом. У меня был захардкожен localhost в параметрах и не сразу получилось заменить на переменную.

Теперь я пытаюсь также побороть rabbitmq. У него также в параметрах конфигурации указан localhost, а в докере для общения между сервисами нужно, чтобы была указана ссылка на сервис, название контейнера, например. Ввести в конфигурацию переменную через конструкцию "${}" почему-то не выходит. Пробую другими путями.

Хочу попробовать с настройкой network в докер-композ, возможно получится. Это какая-то настройка общей сети для всех контейнеров, возможно поможет. Либо буду искать другие варианты.

Потом нужно будет заняться рефакторингом. В понедельник был смешной момент - один из моих методов (калькулятор дистанции между координатами) попал в презентацию лекции по анти-паттернам😅 Вот так вот и переводи сложные формулы с интернета на джава после этого 😁 Придётся теперь узнать, что считается в формуле, которая выдаёт у меня промежуточное значение "а" для вычисления дистанции, через переменную "с". 😂

P.S. Победа!! Сумела засунуть переменную в конфигурацию и переопределила ее в докер-композ! 🥳
🔥9😁1
Всем привет!

Задание на выходные на стажировке у нас было подключить Spring Security по OAuth2 стандарту.

Это такой принцип, при котором существует сервер-шлюз, который перехватывает все запросы, переадресовывает их на сервер аутентификации, который проверяет логин и пароль и, если всё хорошо, выдает токен. С этим токеном, сервер-шлюз перенаправляет запросы на серверы-ресурсы, где хранятся данные пользователей.

Эту тему я ещё изучаю, поэтому не полностью сложилась картина, как это всё работает. Но после последнего задания, стало чуть понятнее.

До этого я как-то с сокурсником обсуждала, как отсеиваются запросы, поступающие напрямую к серверам-ресурсам. Мы подумали, что если ввести адрес напрямую (указать правильный адрес и порт), можно получить доступ к информации без аутентификации.

Такой пример я действительно видела в одном туториале от индуса на ютюбе. Пока он тестировал, он случайно ввёл не тот порт и попал на сервер с ресурсами без какого-либо пароля.

Нам на стажировке дали примерный код для подключения двух дополнительных модулей и, когда у меня уже всё получилось, я убедилась, что напрямую никакого доступа не будет к защищенной информации при правильной настройке.

Нам дали пример с упрощением и я сначала амбициозно подумала, что смогу убрать упрощение и настроить с не заданным пользователем. Когда встретились первые сложности, я ненадолго отложила эту идею до того, как получится по-простому.

Даже с похожим кодом из образца настройка далась не сразу. Но думаю, что обязательно в своем проекте подключу как нужно опираясь на книгу по Security. Временно не получалось ее читать, так и осталось мне 3-4 главы. Но надеюсь скоро всё наладится)
👍6👏4
Всем привет!

У меня подходит к концу стажировка, вчера было последнее занятие, 7го ноября экзамен и итоговое собеседование будет 13 ноября.

Были интересные сложные задания, в итоге получился большой многомодульный проект, относительно моих предыдущих. Но, конечно, не сравнить с реальными проектами. В нем есть, что дорабатывать, но думается мне поработать над своим клоном курсеры.

Начала не очень давно смотреть курс по микросервисам от Amigoscode, у кого хорошо с английским - советую. Этот курс помог мне с настройкой Feign клиента, RabbitMQ. Дальше по курсу будет переход на кафка и, если не ошибаюсь, kubernetes.

Кстати, немного посмотрела ознакомительное видео на тему kubernetes, увидела что это мощный инструмент, в котором можно сделать так, чтобы было много копий нашего приложения, как бы в изолированных контейнерах. Можно настроить, чтобы в случае, если наше приложение (или база данных) упадет, автоматически запустилась его (ее) копия.
👍8🔥5