Developer's Sandbox
868 subscribers
3 photos
5 videos
46 links
Опыт и самообучение практикующего разработчика

Связь с автором: @alpa011235
Download Telegram
Что делать в случае возникновения циклической зависимости?

Когда бин A ссылается на бин B, а бин B ссылается на бин A, возникает циклическая зависимость, в таком случае Spring не сможет создать контекст если не предпринимать никаких дополнительных действий и будет выброшено исключение BeanCurrentlyInCreationException.

В документации говорится о том что в таком случае можно использовать setter injection. Однако помимо этого можно использовать аннотацию Lazy, в таком случае вместо реальной зависимости изначально будет инжектиться прокси, а когда зависимость понадобится, вместо прокси будет создана реальная зависимость.

Тем не менее лучшим решением здесь будет пересмотреть код и избавиться от циклических зависимостей, например создать бин C, который будет вызывать в правильном порядке бин A и B, либо будет использован в бине A и B как некоторая шаренная функциональность, которая необходима обоим бинам.

Теорию можно посмотреть и продебажить на рабочем примере — 🐙Github

#sandbox_spring_context #annotation_based_configuration

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Какие бывают способы Dependency Injection?

Dependency injection можно выполнить следующими способами, которые отличаются местонахождением аннотации Autowired:

— поле (введено в annotation-based configuration)
— сеттер
— конструктор

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

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

Предпочтительнее использовать инъекцию через конструктор (заметка в документации — Constructor-based or setter-based DI?”), в таком случае мы имеем immutable компоненты, которые возвращаются клиенту в полностью проинициализированном виде. Объект изначально создается с необходимыми зависимостями, а не создается пустым, а после чего получает зависимости.

Наиболее компактный вариант, использовать RequiredArgsContructor из библиотеки Lombok, и объявлять зависимости как final поля. В таком случае, учитывая что если у класса 1 конструктор, то аннотация Autowired не нужна (заметка об этом в документации), и этот конструктор будет использован для Dependency injection.

Теорию можно посмотреть и продебажить на рабочем примере — 🐙Github

#sandbox_spring_context #annotation_based_configuration

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Что такое Happens-before и какие способы воспроизведения этой гарантии есть в Java?

Happens-before позволяет гарантировать порядок видимости операций между потоками.
Это означает что если есть поток T1 и T2, действия a1 и a2, выполняемые в потоках Т1 и Т2 соответственно, и действие a1 происходит до (happens-before) действия a2, то во время выполнения Т2, ему будут видны все изменения, произошедшие в a1 потоком T1.

В Java happens-before происходит в следующих случаях:

1⃣ Default initialization — инициализация по-умолчанию (0, false, null) при создании переменной происходит до первого действия в каждом потоке
2⃣ Final thread action — последнее действие в Т1 происходит до завершения вызова T1.join() в T2
3⃣ Monitor lock — освобождение монитора происходит до последующего захвата того же монитора
4⃣ Same thread actions — выполнение действий в одном потоке происходит в заданном в программе порядке
5⃣ Start thread action — действие запуска потока .start() происходит до первого действия в этом потоке
6⃣ Thread interrupt action — прерывание потоком Т1 потока Т2 происходит до обнаружения прерывания в потоке Т2
7⃣ Volatile — записи до volatile переменной гарантированно будут выполнены до записи в переменную volatile, а чтение volatile переменной гарантированно будет до чтения последующих переменных

Теорию можно посмотреть и продебажить на рабочих примерах — 🐙Github

#sandbox_java #java_memory_model

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Для чего применяются ключевые слова volatile и synchronized?

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

В таком случае у нас возникает проблема Visibility, когда изменения общей переменной могут быть не видны в других потоках.
Для того чтобы решить эту проблему можно пометить переменную как volatile, в таком случае все записи и чтения будут осуществляться с общей памятью, а не с кешом процессора.

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

Один из вариантов решения проблемы Mutual Exclusion это использовать ключевое слово synchronized, в таком случае даже если операции не атомарные, выполнять критическую секцию будет только один поток, а переменные с которыми взаимодействует поток внутри synchronized блока будут также записаны или прочтены из общей памяти.

Таким образом volatile решает проблему Visibility без Mutual Exclusion и может быть использован когда нам неважно что множество потоков работают с переменной параллельно, а важно чтобы они видели изменения.
В свою очередь synchronized решает обе проблемы Visibility и Mutual Exclusion и может быть использован когда нам необходимо чтобы работа с переменной производилась последовательно и также была видна другим потокам.

Теорию можно посмотреть и продебажить на рабочих примерах — 🐙Github

#sandbox_java #java_memory_model

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Как Spring создает бин и какой его жизненный цикл?

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

BeanDefinitionReader создает объекты BeanDefinition, каждый из которых содержит метаинформацию о бине, такую как метод инициализации, зависимости, имя класса и другую информацию, необходимую для создания экземпляра бина. Создание объектов бинов осуществляется с помощью BeanFactory.

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

С учетом создания BeanDefinition, можно выделить следующие шаги в жизненном цикле бина:

0⃣ BeanFactoryPostProcessor.postProcessBeanFactoryпозволяет изменить BeanDefinition до создания бина.
1⃣ Instantiationсоздание объекта бина с помощью конструктора.
2⃣ Properties population установка зависимостей через сеттеры, также может быть объединено с первым шагом, если используется конструктор с параметрами.
3⃣ BeanNameAwareполучение доступа к имени бина.
4⃣ BeanFactoryAwareполучение доступа к BeanFactory.
5⃣ ApplicationContextAwareполучение доступа к ApplicationContext.
6⃣ BeanPostProcessor.postProcessBeforeInitializationпозволяет модицифировать все существующие бины до инициализации.
7⃣ PostConstruct метод инициализации через аннотацию.
8⃣ InitializingBean.afterPropertiesSetметод инициализации через интерфейс (не рекомендуется Spring, т.к. есть аннотация).
0⃣ Init method from configurationметод инициализации через Java-based конфигурацию либо XML-based конфигурацию.
1⃣0⃣ BeanPostProcessor.postProcessAfterInitialization позволяет модицифировать все существующие бины после инициализации.
1⃣1⃣ SmartInitializingSingleton.afterSingletonsInstantiatedпозволяет выполнить дополнительные действия после полной подготовки бина.

Также, например, в случае gracefully shut down буду вызваны методы перед завершением работы приложения:

1⃣2⃣ PreDestroyметод с действиями перед удалением из контекста через аннотацию.
1⃣3⃣ DisposableBean.destroyметод с действиями перед удалением из контекста через интерфейс (не рекомендуется Spring, т.к. есть аннотация).
1⃣4⃣ Destroy method from configurationметод с действиями перед удалением из контекста через Java-based конфигурацию либо XML-based конфигурацию.

Spring рекомендует реализовывать методы *Aware только для инфраструктурных бинов, а не для сервисов или других компонентов, чтобы избежать привязки к специфическим контрактам Spring.

Теорию можно посмотреть и продебажить на рабочих примерах — 🐙Github

#sandbox_spring_context #bean_lifecycle

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Делюсь открытыми материалами для подготовки к собеседованию в Яндекс и Тинькофф:

Тинькофф:
📌 об этапах собеседования и материалы для подготовки
📌 о секции системного дизайна

Яндекс:
📌 гайд по интервью в Яндекс.Облако со всеми материалами в одном месте
📌
об этапах собеседования
📌 тренировочные задачи
📌 отдельная площадка для тренировки задач
📌 числа которые нужно знать и о системном дизайне
📌 об опыте прохождения архитектурных секций
📌 fast track программа для прохождения в Яндекс

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

#note #sources

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7
Что такое Apache Kafka и какие области ее применения?

Apache Kafka — распределенная стриминговая платформа с открытым исходным кодом.
Можно встретить также другие формулировки:
— распределенный лог коммитов (distributed commit log)
— с точки зрения разработчика работающего с Kafka это персистентная очередь (такая формулировка относиться не ко всем сценариям использования)

Изначально Kafka была разработана небольшой командой инженеров в 2011 году компанией LinkedIn.

Задача стояла в реализации системы для отслеживания активности пользователей (Activity tracking). Т.е. каждый клик, на какую страницу пользователь зашел, где поставил лайк, сколько потратил время на странице и т.д.

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

Где еще применяется Apache Kafka?
Других сценариев для применения кафки большое количество. Например:
Messaging — другие приложения могут общаться между собой через кафку.
Metrics and logging collection - другие приложения могут посылать метрики и логи в кафку, которые затем будут переданы в системы для мониторинга.
Commit log — изменения в базе данных могут паблишиться в кафку и другие приложения могут отслеживать эти изменения.
Stream processing — обработка событий в реальном времени, например получение данных из нескольких источников, их преобразование (ETL процессы), агрегирование и сохранение в базу данных.

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

Однако с примером можно ознакомиться уже сейчас, в последующем я буду ссылаться на этот же пример. Кафка кластер из двух брокеров, Zookeeper и Kafka-UI в docker-compose. Spring Boot интеграция с Kafka кластером и удобные команды для исследования поведения приложения через Spring Shell.

Все это можно найти по ссылке — 🐙Github

#sandbox_kafka #spring_boot_kafka

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
В нашем примере есть Kafka Cluster, состоящий из двух Kafka Broker’ов и Zookeeper. В качестве клиентов используются Spring Boot приложения - Consumer и Producer, где Producer передает сообщения, а Consumer их получает. Используется топик с именем “demo-topic" состоящий из четырех партиций и с фактором репликации равным 2.

На базе вышесказанного коротко рассмотрим первую часть основных сущностей Apache Kafka:

Kafka Broker (Kafka Server, Kafka Node) — посредник между Consumer’ами и Producer’ами. Он отвечает за прием, выдачу и хранение сообщений.

Kafka Cluster — группа связанных Kafka Broker’ов.

Kafka Controller — один из брокеров в кластере, автоматически выбранный для выполнения инфраструктурных задач. В кластере может быть только один активный контроллер, а в случае его отказа происходит автоматический выбор контроллера среди доступных брокеров. В его задачи входит отслеживание состояния брокеров, выбор лидер реплик, автоматическая балансировка кластера.

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

Message (Record) — единица данных в системе, имеет по-умолчанию максимальный размер 1МБ. Состоит из необязательного параметра Key (массив байт), который может быть использован, например, для выбора конкретной партиции. Value (массив байт), содержащий тело сообщения. Headers (последовательность пар ключ-значение) для передачи дополнительных параметров. Метаданные о сообщении, например - timestamp, offset, partition id.

Topic — логическая единица организации сообщений. По аналогии с папкой в файловой системе, в которой хранятся файлы, в топике хранится набор сообщений. Топик является multi-producer и multi-subscriber, это означает что он может иметь множество Producer’ов и Consumer’ов, либо не иметь их вообще. Сообщения из топика могут быть прочитаны множество раз, после чтения Consumer’ом они не удаляются. Вместо этого можно указать время жизни сообщений.

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

Replication — механизм обеспечения отказоустойчивости и высокой доступности с помощью создания копий (реплик) партиций между брокерами. Конфигурация параметра replication.factor позволяет указать количество реплик, которое будет создано для каждой партиции. Реплики одной партиции не могут находиться на одном брокере.

Отрефакторил docker-compose.yaml, исправил batch обработку в Сonsumer’e, теперь он обрабатывает по 3 сообщения и это конфигурабельно.
Можно ознакомиться с примером по ссылке — 🐙Github.

#sandbox_kafka #spring_boot_kafka

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
В продолжение предыдущего поста, вторая часть основных сущностей Apache Kafka:

Leader — главная реплика, назначенная Kafka Controller’ом, особенность которой заключается в том, что операции чтения и записи происходят только с ней (с версии 2.4 Kafka поддерживает чтение с реплик). Может случится ситуация, когда лидер реплики расположены неравномерно между брокерами, и один брокер имеет большую часть нагрузки, а другие хранят follower реплики. Не всегда автоматическая балансировка позволяет это предотвратить и необходимо балансировать кластер вручную, учитывая знание нагрузки на определенные топики.

Follower — копия лидер реплики. Для синхронизации данных с лидером используются два подхода, в первом случае follower реплика сама периодически опрашивает лидера о новых сообщениях, а во втором случае лидер при получении сообщения также записывает его в follower, в таком случае follower называется ISR - in-sync replica.

Producer — любой клиент, отправляющий сообщения брокерам. Отправляя сообщения, можно как ожидать подтверждения со стороны Kafka так и не ожидать, в зависимости от целей это можно сконфигурировать с помощью параметра acks, который имеет следующие значения:
* 0 — сообщение будет отправлено без ожидания какого-либо подтверждения со стороны Kafka. В таком случае сообщения могут теряться.
* 1 — сообщение будет отправлено с ожиданием подтверждения что запись была произведена в Leader реплику без ожидания подтверждений от ISR Follower’ов. Сообщения могут дублироваться в случае если брокер с Leader репликой сломался до того как произошла репликация Follower’ам.
* all — сообщение будет отправлено с ожиданием подтверждения что запись была произведена в Leader реплику и реплицирована ISR Follower’ам.

Consumer — любой клиент, принимающий сообщения от брокеров. Kafka использует pull-based подход. Это означает, что приложение, работающее с Kafka само опрашивает брокеров на предмет наличия сообщений. Для организации параллельной обработки можно объединить несколько Consumer’ов в Consumer Group указав им одинаковый group id. В группе равномерно распределяются партиции для каждого Consumer’a, однако чтобы исключить ситуацию, когда сообщение будет прочитано дважды Consumer’aми из одной группы, Consumer не может получать сообщения из партиции из которого их уже получает другой Consumer из этой же группы. Т.е. если Consumer’ов в группе будет больше чем партиций в топике, какие-то из них будут просто ожидать и не читать сообщения.

По практике:
Добавил мониторинг Kafka кластера с помощью Prometheus и Grafana как с помощью метрик из официального jmx-exporter’a, так и с помощью стороннего kafka-lag-exporter’a для просмотра consumer lag’a.
Подробнее о мониторинге и о consumer lag’e поговорим в будущем, а сейчас можно посмотреть пример по ссылке — 🐙Github

#sandbox_kafka #spring_boot_kafka

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Посмотрел видео https://www.youtube.com/watch?v=QUOynbWKwZo&t=300s на скорости x2 (ссылка специально с таймингом где начинается рассказ)

На мой взгляд для middle/senior уровня здесь мало что можно нового узнать, разве что для повторения.

Вопросы, которые здесь рассматриваются:
— Что такое хорошая архитектура кода?
— Метрика архитектуры кода — Time To Market, имеется ввиду от времени на разработку до конца тестирования
— Указывается что основа для архитектуры кода, это:
* Архитектура системы (Microservices vs Monolith, Sync vs Async)
* Framework (в примерах рассматривается Spring)
* Знания разработчика
— Рассматриваются принципы хорошей архитектуры:
* DRY
* KISS
* SOLID (просто упоминается, но не разбирается. Говорится лишь о том, что Spring использует эти принципы)
— Разбираются слои в архитектуре, с примером какие классы какому слою принадлежат
— Publisher-subscriber паттерн для реализации прогрева кеша
— Приводятся виды паттернов проектирования

Еще один интересный момент, приводится пример, где следуя принципу DRY, избавляются от дубликата кода. Пример заключается в следующем:
Есть 2 метода, помеченные аннотацией GetMapping, в них есть одинаковые параметры limit и offset, помеченные аннотацией RequestParam, а также нужно валидировать их значения.

Для того чтобы избежать дубликата кода, используем знание Spring фреймворка. Создается класс Paging с полями limit и offset, для валидации используется spring-boot-starter-validation и аннотация Valid перед параметром в методе контроллера, и аннотации Positive и PositiveOrZero над полями класса Paging.
Чтобы объект был создан из двух RequestParam, реализуется PagingParamMethodArgumentResolver, который наследуется от класса из Spring - RequestParamMethodArgumentResolver. Создается аннотация PagingParam для того чтобы помечать такие параметры, по аналогии с RequestParam.

Не совсем понял почему именно в примере наследуются от класса RequestParamMethodArgumentResolver вместо реализации интерфейса HandlerMethodArgumentResolver, что на мой взгляд правильнее, т.к. RequestParamMethodArgumentResolver создан для обработки аннотации RequestParam. А также если мы создаем объект Paging как делается в примере, у нас не будет работать валидация несмотря на аннотацию Valid. (ред. Если все-таки добавить еще аннотацию Validated над классом, то валидация будет работать)

В итоге, можно сделать тоже самое, но значительно проще. Можно просто создать класс Paging и указать его в качестве параметра метода. Spring расценит его поля как query параметры и сам создаст объект, не нужно реализовывать HandlerMethodArgumentResolver, и в таком случает работает и валидация.

RequestParam аннотация применяется по-умолчанию если нет никаких других аннотаций над параметрами метода контроллера (об этом в документации - https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-controller/ann-methods/requestparam.html)

А если нам все-таки нужно реализовать свой HandlerMethodArgumentResolver и использовать валидацию через Valid, то тут уже не так просто, об этом можно почитать тут (https://stackoverflow.com/questions/18091936/spring-mvc-valid-validation-with-custom-handlermethodargumentresolver) (см. выше)

Написал пример online-library, где используется Spring Data, Spring MVC, Postgres в Docker’e вместе с pgAdmin, миграция через Flyway, однако в контексте данной статьи интересует пример с Paging классом, описанный мною выше, только в моем случае я назвал его Pagination. Посмотреть можно по ссылке — 🐙Github

#note #sources #video_review #sandbox_spring_web #online_library

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥131
Прочитал книгу "От Джуна до Сеньора. Как стать востребованным разработчиком", автор - Владимир Швец.

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

Книга мне понравилась, читается быстро и легко, как обзор и повторение ключевых моментов в разработке как с технической стороны, так и со стороны взаимодействия с людьми и отношению к работе, не смотря на то, что некоторые вещи очевидные.

Книга разделена на 3 основные секции (1. Код 2. Люди 3. Я). Читать можно в любом порядке, то что будет интересно.

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

Для меня здесь было интересно повторить в очередной раз о теме перфекционизма, например не рефакторить код 3 недели вместо того чтобы добавлять приоритетный функционал, уметь останавливать себя не смотря на тягу к красивому коду.
Различать программирование для себя и для работы не смотря на тягу попробовать новые технологии или обновиться до новой версии фреймворка или языка.

Помимо этого можно еще упомянуть следующие моменты:
— О здравом подходе к абстракциям в коде (KISS).
— Об отделении себя как личности от результатов твоей работы, например, при ревью кода не нужно воспринимать комментарии как личное оскорбление тебя как человека, можно рассматривать код как инструмент к достижению общей цели и у каждого участника команды общий интерес чтобы все работало как нужно. Конечно тут зависит еще от людей и их характеров, но мысль правильная.

Найти книгу достаточно просто, может кому-то будет интересно как и мне для повторения и сравнения опыта, а может кто-то узнает что-то новое.

#note #sources #book_review

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍212
После обсуждения предыдущего поста, решил составить список книг.

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

То что подойдет начинающим помечено 🐣.

Перейдем к списку:

📚 Java:
- 🐣 Core Java Volume I--Fundamentals (Core Series) 11th Edition - Cay Horstmann
- 🐣 Thinking in Java - Bruce Eckel
- 🐣 Java: The Complete Reference - Herbert Schildt
- 🐣 Head First Java: A Brain-Friendly Guide - Kathy Sierra, Bert Bates, Trisha Gee
- 📖 Effective Java, 3rd Edition - Joshua Bloch
- 📖 Java Puzzlers: Traps, Pitfalls, and Corner Cases - Joshua Bloch, Neal Gafter
- 📖 Java Concurrency in Practice - Brian Goetz

📚 Алгоритмы и структуры данных:
- 🐣 Grokking Algorithms: An Illustrated Guide for Programmers and Other Curious People - Aditya Bhargava
- 📖 Algorithms - Robert Sedgewick
- 📖 Introduction to Algorithms - Thomas H. Cormen

📚 Архитектура и системный дизайн:
- 📖 Clean Architecture: A Craftsman's Guide to Software Structure and Design - Robert C. Martin
- 📖 System Design Interview – An insider's guide - Alex Xu
- 📖 Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems - Martin Kleppmann
- 📖 Building Microservices: Designing Fine-Grained Systems - Sam Newman

📚 Паттерны проектирования:
- 📖 Design Patterns: Elements of Reusable Object-Oriented Software - Gamma Erich, Helm Richard, Johnson Ralph, Vlissides John
- 📖 Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software - Eric Freeman, Elisabeth Robson
- 📖 Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions - Gregor Hohpe, Bobby Woolf

📚 SQL:
- 🐣 Learn SQL The Hard Way - Zed Shaw

📚 Computer science:
- 🐣 Code: The Hidden Language of Computer Hardware and Software - Charles Petzold
- 🐣 Computer Science Distilled: Learn the Art of Solving Computational Problems - Wladston Ferreira Filho

📚 Разработка:
- 📖 Clean Code: A Handbook of Agile Software Craftsmanship - Robert C. Martin
- 📖 Refactoring: Improving the Design of Existing Code - Martin Fowler
- 📖 Code Complete: A Practical Handbook of Software Construction - Steve McConnell
- 📖 Working Effectively with Legacy Code - Michael Feathers
- 📖 The Pragmatic Programmer: Your Journey To Mastery - David Thomas, Andrew Hunt
- 📖 Domain-Driven Design: Tackling Complexity in the Heart of Software - Eric Evans
- 📖 Cracking the Coding Interview: 189 Programming Questions and Solutions - Gayle Laakmann McDowell
- 📖 Test Driven Development: By Example - Kent Beck

Буду рад, если в комментариях вы напишете, с какими еще книгами следует ознакомиться 📚

#note #sources

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥42
Что такое DLT и как это реализовать в Apache Kafka?

DLT (Dead Letter Topic) или DLC (Dead Letter Channel) или DLQ (Dead Letter Queue) — это подход для обработки недоставленных сообщений, которые не удалось обработать в нормальном режиме.

Представим, что идет поток сообщений через Apache Kafka. Producer их посылает, Consumer их принимает.

При обработке Consumer'ом сообщений, может возникнуть исключение, по самым разным причинам, например, неправильный формат данных, NPE, неправильное значение определенного поля в сообщении и т.д. И нам необходимо определить поведение для таких ситуаций. И одним из способов является DLT.

Выбираем топик, для которого мы хотим обрабатывать ошибки, например, demo-topic. Создаем дополнительный топик для сообщений с ошибками, например, demo-topic.failures.
Когда Consumer будет получать исключение в ходе обработки сообщения, он будет отправлять это сообщение в demo-topic.failures с дополнительной информацией в Headers о том, какое исключение было выброшено.

Помимо этого, можно реализовать несколько попыток повторной отправки сообщения, прежде чем оно все-таки попадет в DLT. В Spring это уже все реализовано, остается только правильно сконфигурировать.

Какие преимущества дает такой подход?
— Отделение основного потока сообщений, от потока ошибок
— Можно настроить удобный мониторинг для разных типов исключений
— Можно хранить ошибки дольше и более подробно исследовать их причины
— Можно вручную исправить ошибку и переотправить сообщение из demo-topic.failures

Когда не стоит использовать такой подход и в чем его минусы?
— Усложнение архитектуры. Если исключения возникают редко, и вы можете их обработать более простым способом, можно не усложнять.
— Не стоит использовать DLT для проблем с соединением Consumer'a с другими системами. Это ответственность приложения consumer'a.
— Дополнительная нагрузка на сеть и дополнительное место для хранения ошибок в отдельном топике.

Практика:
— Добавил удобную возможность посылать сообщения, которые вызывают ошибки через Spring Shell.
— Добавил механизм ретраев через ExponentialBackOffWithMaxRetries и интеграционный тест с помощью testcontainers, который проверяет как работает DLT.

Все это по ссылке — 🐙Github

#sandbox_kafka #spring_boot_kafka

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍4👀2
Что такое SSL сертификаты и для чего они нужны?

Рассмотрим на примере:
У нас есть сайт, где клиент вводит персональные данные (например, данные банковских карточек, паспорта, номера телефонов и т.д.)

Если мы используем на сайте HTTP протокол, то получаем следующие проблемы:
Персональные данные передаются по сети в открытом виде как обычный текст, и злоумышленник, имеющий доступ к сети, может эти данные получить либо изменить.
Поисковики (google и др.) понижают в результатах поиска сайты, использующие HTTP
Браузеры (google chrome и др.) перед переходом на HTTP сайт показывают предупреждение, что он небезопасный
Нет доказательства что наш сайт, принадлежит нашей организации. Т.е. нету сертификата, в котором это прописано. И злоумышленники могут создавать копии нашего сайта.

Для решения этих проблем, нам необходимо перейти на HTTPS. И здесь мы вводим понятия SSL и TLS:
SSL — Secure Sockets Layer — протокол в криптографии для безопасной передачи данных по сети.
SSL является устаревшим и вместо него используется разработанный на его основе TLS — Transport Layer Security, однако терминология часто встречается из старого протокола, и когда говорят SSL сертификат, имеют ввиду TLS сертификат.

HTTPS использует TLS для обеспечения безопасной передачи данных. Фактически HTTPS это HTTP, который использует уровнем ниже TLS.

Благодаря использованию TLS мы получаем:
Конфиденциальность — данные передаются по сети в зашифрованном виде, теперь злоумышленник не увидит наши персональные данные как обычный текст.
Подлинность — в сертификате нашего сайта будет связь между ним и нашей организацией. Перед отправкой данных, клиент проверит сертификат и сможет убедиться, что он попал на оригинальный сайт.
Целостность — данные гарантированно будут получены клиентом/сервером в том виде, в котором они были отправлены клиентом/сервером. Злоумышленник не сможет изменить данные если он их перехватит. (Достигается это благодаря вычислению MAC (Message Authentication Code). Клиент вычисляет хеш сообщения и передает его серверу вместе с сообщением, сервер вычисляет хеш полученного сообщения и сравнивает с хешом полученным от клиента. Если хеш совпадает, значит сообщение не было изменено.)

Сама реализация протокола TLS требует наличие сертификата. Без него работать не будет.

SSL (TLS) сертификат — логически представляет собой цифровой паспорт сервера, а физически это файл, обычно с расширением .cer или .pem

В нем содержится следующая основная информация:
📝 Subject — данные о владельце сертификата (содержит много опциональных полей, например в CN (Common Name) обычно указывают домен)
📝 Issuer — данные о подписчике сертификата (например, можно увидеть какой CA (Certificate Authority) подписал этот сертификат)
📝 Public key — публичный ключ сертификата, используется для проверки подписи и шифрования session key (о нем позже)
📝 Valid from — дата создания сертификата
📝 Valid until — срок действия сертификата
📝 Signature — цифровая подпись сертификата, например подписанная CA

Теперь мы представляем что это и для чего это нужно. Остаются вопросы:
Откуда взять сертификаты?
Какие виды сертификатов есть?
С технической точки зрения, как клиент и сервер используют сертификат?

Об этом в следующих статьях. Однако для тех, кто хочет быстрее посмотреть пример Spring Boot сервера c mTLS и скрипт с эмуляцией выдачи CA клиентского и серверного сертификата, можно перейти по ссылке — 🐙Github

#sandbox_spring_web #https

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍285🔥4🤯1
Ответим на часть вопросов из предыдущей статьи:
Откуда взять сертификаты?
Какие виды сертификатов есть?

Сертификаты можно получить несколькими способами:
— Сгенерировать самостоятельно
— Получить бесплатно, либо купить в специальной организации, имеющей статус Сertificate Authority (CA)

⚠️ Если любой пользователь может генерировать сертификаты, то как браузер либо любой другой клиент, общающийся с HTTPS сервером, понимает что сертификату сервера можно доверять?

Для ответа на этот вопрос у клиента есть изначальный набор сертификатов, и доверенными сертификатами считаются только те, что находятся в этом наборе, который еще называют truststore.
В браузерах, операционных системах и JDK такие наборы сертификатов идут сразу с установкой. А сами сертификаты берутся у доверенных CA компаний (Например DigiCert, Let's Encrypt).
Это значит, что даже если вы сгенерируете свой сертификат, доверять ему смогут только приложения, где у вас есть прямой доступ к их truststore.

Таким образом, можно выделить виды сертификатов по уровню доверия к ним:

📝 Self-signed — самоподписанные сертификаты. Можно сгенерировать самостоятельно, например, через команду openssl. Доверять таким сертификатам сможете только вы, и пользователи, которые специально добавят их в свой truststore.
Технически, корневые сертификаты от CA, установленные по-умолчанию в браузерах и ОС, тоже являются самоподписанными, но им принято доверять.

Если мы получаем сертификат через CA, то в зависимости от количества проверок со стороны CA, есть следующие виды сертификатов:

📝 DV (Domain Validation) — CA организация проверяет, что указанный домен принадлежит действительно человеку, который обратился за получением сертификата. Это самая минимальная проверка, можно провести автоматически и получить сертификат бесплатно, так делает CA организация — Let's Encrypt.

📝 OV (Organization Validation) — CA помимо домена, проверяет еще что ваша организация действительно существует и у нее есть юридический адрес. Такой сертификат будет уже платный.

📝 EV (Extended Validation) — CA помимо предыдущих проверок, проведет ряд дополнительных проверок вашей организации. Такой сертификат будет стоить еще дороже. Больше подходит корпорациям, например, такой сертификат можно посмотреть на сайте apple.

Остаются вопросы, которые мы рассмотрим в следующих статьях:
С технической точки зрения, как клиент и сервер используют сертификат? (Поговорим о TLS-handshake)
Если мы получили сертификат выданный CA, то как клиенты будут ему доверять? Ведь только что выданный сертификат не появится во всех ОС и браузерах как доверенный в их truststore. (Поговорим о certificate chain)

Заранее добавил пример, демонстрирующий работу с цепочками сертификатов — 🐙Github

#sandbox_spring_web #https

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥2
Ответим на вопрос из предыдущей статьи:
Если мы получили сертификат выданный CA, то как клиенты будут ему доверять? Ведь только что выданный сертификат не появится во всех ОС и браузерах как доверенный в их truststore.

Чтобы ответить на этот вопрос, нужно понимать как проверяется сертификат.

Рассмотрим на примере:
Перед запросом сертификата от CA, мы генерируем private key и CSR (Certificate Signing Request). В CSR хранится информация о нашем сайте (например, в поле subject указано поле CN=<домен>), а также public key, связанный с нашим private key.

Что такое private key и public key?
Это понятия из криптографии, а именно из ассиметричного шифрования (например, алгоритм RSA). Здесь нам важно понимать что существует связанная пара ключей:
— Public key можно передавать другим людям, он используется для шифрования и проверки signature (цифровая подпись)
— Private key следует хранить в секрете, он используется для дешифрования и создания signature

После того как CA получил CSR, используя его, а также свой CA сертификат и CA private key, он генерирует нам сертификат (в поле issuer нашего сертификата будет указана информация из subject'a CA сертификата) и мы устанавливаем его на сервер.

Что на этом этапе есть на нашем сервере?
— Сгенерированный нами private key
— Сгенерированный нам от CA сертификат, содержащий наш public key и подпись, сделанную CA private key

А что есть у клиента, который отправит запрос на наш сервер?
— У него есть только CA сертификат, по-умолчанию установленный в truststore его браузера

Теперь клиент отправляет запрос на сервер, и проверка сертификата происходит следующим образом:
1⃣ Получаем сертификат сервера
2⃣ Смотрим значение issuer и ищем в truststore сертификат, у которого такой subject (мы его находим, это CA сертификат)
3⃣ Берем public key из CA сертификата, а signature берем из сертификата сервера
4⃣ Т.к. signature была сделана используя CA private key, то используя CA public key мы проверяем ее и достаем из signature информацию о hash'e сертификата сервера.
5⃣ Смотрим какой алгоритм использовался для генерации hash'a сертификата сервера
6⃣ Откидываем signature и считаем hash для body (body это весь файл сертификата, кроме signature)
7⃣ Если hash из signature и только что рассчитанный hash для body равны, то значит сертификат сервера действительно был подписан CA и ему можно доверять.

Таким образом, имея только корневой CA сертификат, мы можем проверять все выданные этим CA сертификаты.

Это позволяет создавать цепочки сертификатов (certificate chain):
— Например, один крупный CA выдает оптом сертификаты другому CA поменьше, а он уже выдает сертификаты физическим лицам.
— Тогда на сервере будет цепочка сертификатов от разных CA (обязательно в той последовательности, в которой они выдавались)
— Но клиенту все равно достаточно иметь только один корневой сертификат в truststore, который от крупного CA
— Проверка по алгоритму, описанному выше, пройдет по всей цепочке, начиная от корневого сертификата

Этот алгоритм можно полностью самостоятельно провести на практике, я описал скрипт для ручной проверки сертификата (поиск по Manual certificate validation), а также добавил https клиент — 🐙Github

#sandbox_spring_web #https

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍141
🔤🔤🔤🔤

Sandbox 📦
🔤Сравнение JDBC, Spring JDBC, Hibernate, Spring Data JPA
🔤Логирование JDBC запросов
🔤Обзор Spring Data JDBC, MyBatis, JOOQ
🔤Что такое Spring Boot и для чего он используется?

Java
Sandbox ☕️
🔤В чем разница между анонимным классом и λ-выражением?
🔤Какие бывают типы λ-выражений?
🔤Как Capturing λ-выражение влияет на GC?
🔤Всегда ли method reference ведет себя как и λ-выражение?
🔤Что такое Happens-before и как воспроизвести эту гарантию?
🔤Для чего применяются volatile и synchronized?

Spring Context Sandbox 🌱
🔤Annotation-based config и как зарегистрировать бин в runtime?
🔤Что делать в случае возникновения циклической зависимости?
🔤Какие бывают способы Dependency Injection?
🔤Как Spring создает бин и какой его жизненный цикл?🫘

Spring Web Sandbox 🌱
🔤Обзор видеоурока "Архитектура кода (Java)"
🔤Что такое SSL сертификаты и для чего они нужны?📜
🔤Откуда взять сертификаты и какие есть виды?📜
🔤Как происходит проверка сертификата?📜

Spring Data JPA Sandbox 🌱
🔤Какие существуют типы связей в JPA?

PostgreSQL Sandbox 🐘
🔤Какие существуют типы связей в реляционных БД?

Apache Kafka Sandbox📖
🔤Что такое Apache Kafka и какие области ее применения?
🔤Основные сущности Apache Kafka. Часть 1
🔤Основные сущности Apache Kafka. Часть 2
🔤Что такое DLT и как это реализовать в Apache Kafka?
🔤Что такое delivery semantics в Apache Kafka?
🔤Консольные инструменты Apache Kafka

Other📐
🔤Более подробное описание канала
🔤Материалы для подготовки в Яндекс, Тинькофф
🔤Обзор книги “От Джуна до Сеньора"
🔤Список литературы
🔤Версии Java
🔤С наступающим 2024 годом🎄
🔤С наступающим 2025 годом🎄
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4011🤯3
Developer's Sandbox pinned «🔤🔤🔤🔤 Sandbox 📦 🔤Сравнение JDBC, Spring JDBC, Hibernate, Spring Data JPA 🔤Логирование JDBC запросов 🔤Обзор Spring Data JDBC, MyBatis, JOOQ 🔤Что такое Spring Boot и для чего он используется? Java Sandbox ☕️ 🔤В чем разница между анонимным классом и λ-выражением?…»
Недавно вышла общедоступная версия Java 21, которая является следующей LTS (Long-term support) версией после Java 17

Смотрел, какие новые фичи добавили в язык и захотел поделиться с вами полезным ресурсом, где я обычно смотрю обновления — javaalmanac

Здесь можно найти информацию по каждой версии Java, начиная с первой и заканчивая той, что на данный момент в разработке (Java 22)

Что тут можно найти?
— Ссылки на спецификации — языка, API, виртуальной машины
— Ссылки на release notes
— Если перейти на конкретную версию, то по каждому уровню (JVM, Language, API), можно увидеть список добавленных фич, многие из которых объясняются с примерами
— В колонке "Compare API to" можно выбрать предыдущие версии, сравнив API до самых мелочей, например, между Java 21 и Java 20 добавился метод isEmoji(int) в Character классе

Заодно решил обновить свои примеры на самые последние версии:
— Перешел на Java 21
— Отрефакторил build.gradle и перешел в нем с Groovy на Kotlin
— Обновил все версии библиотек, а где используется docker — обновил версии imag'ей

Теперь структура примеров еще проще:
🌱 sandbox-spring-context
🌱 sandbox-spring-web
📖 sandbox-kafka
☕️ sandbox-java

#note #sources

Меню
Подпишись: @developer_sandbox
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31