java_iibrary | Unsorted

Telegram-канал java_iibrary - Java Portal | Программирование

12073

Присоединяйтесь к нашему каналу и погрузитесь в мир для Java-разработчика Связь: @devmangx РКН: https://clck.ru/3H4WUg

Subscribe to a channel

Java Portal | Программирование

Пессимистическая vs оптимистическая блокировка

Частый вопрос на собеседованиях по backend.

[Пессимистическая блокировка]: -

- Запись недоступна другим потокам, пока текущий поток не закончит с ней работу.
- Даже чтение данных другими потоками невозможно, пока блокировка не снята.
- Пример: EntityManager.lock(entity, LockModeType.PESSIMISTIC_WRITE) в JPA.
- Минусы: снижает производительность при высоком уровне конкуренции.
- Когда использовать: когда критически важна точность данных.

[Оптимистическая блокировка]: -

- Не блокирует данные при чтении, но при сохранении проверяет версию записи.
- Пример: аннотация @Version в JPA (колонка для хранения версии).
- Если версия изменилась другим потоком, выбрасывается OptimisticLockException.
- Минусы: нужно разруливать конфликты.
- Когда использовать: когда чтений много, а вероятность конфликтов низкая.

Какой подход ты чаще используешь в своих проектах?

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Совет: держите код рядом. Следите, чтобы вычисление было как можно ближе к месту, где используется это значение. Это улучшает читаемость и удобство рефакторинга, снижает вероятность багов и делает код более устойчивым к ошибкам.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Spring Boot: можно использовать spring.jpa.hibernate.ddl-auto=validate, чтобы проверять случайные изменения схемы в продакшене.

✅Если что-то не совпадает, приложение не запустится
✅Это можно комбинировать с инструментами миграций, например Flyway или Liquibase

👉 Java Portal

Читать полностью…

Java Portal | Программирование

В Spring Boot можно включить асинхронное логирование, настроив Logback (logback-spring.xml).

✅Лог-сообщения отправляются в очередь и обрабатываются отдельным фоновым потоком.

✅Это снижает узкие места на I/O (ввод-вывод).

Положи конфиг Logback в папку resources:

src/main/resources/logback-spring.xml

Пример:

<configuration>

<!-- Консольный appender, обернутый в async -->
<appender name="ASYNC_CONSOLE" class="ch.qos.logback.classic.AsyncAppender">
<appender-ref ref="CONSOLE" />
<queueSize>5000</queueSize>
<discardingThreshold>0</discardingThreshold>
<includeCallerData>false</includeCallerData>
</appender>

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger - %msg%n</pattern>
</encoder>
</appender>

<root level="INFO">
<appender-ref ref="ASYNC_CONSOLE" />
</root>

</configuration>



👉 Java Portal

Читать полностью…

Java Portal | Программирование

Java 25: апгрейд, который экономит до 30% RAM (без правок кода)

В JDK 25 добавили одну из самых заметных оптимизаций за долгое время: Compact Object Headers (JEP 519).

Что меняется:

- размер заголовка объекта уменьшается примерно с ~12 байт до 8 байт
- меньше памяти на объект -> меньше heap
- меньше heap -> меньше давление на GC
- меньше GC -> сервис быстрее + облако дешевле

Где профит максимальный:
Spring Boot, микросервисы, DTO, records, кэши, в общем всё, где много мелких объектов.

Включается одной опцией:
-XX:+UseCompactObjectHeaders

По отзывам из реальных систем:
снижение heap на 15–30% встречается довольно часто.

Просто протестируй на своих сервисах и забирай “бесплатную” экономию.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Знания по базам данных на техсобесах игнорировать нельзя.

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

Один из ключевых концептов тут это JOIN.

Я собрал понятную шпаргалку по SQL JOIN: с примерами и визуализацией, чтобы быстро уложить в голове.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Продвинутый Map в Java (надо знать)

Если ты хоть раз делал Map<String, List<String>>, этот пост для тебя.

Признайся, все когда-то писали так:

Map<String, List<String>> userTags = new HashMap<>();
userTags.computeIfAbsent("user123", k -> new ArrayList<>()).add("premium");
userTags.computeIfAbsent("user123", k -> new ArrayList<>()).add("verified");


Или вообще вот так:

if (!userTags.containsKey("user123")) {
userTags.put("user123", new ArrayList<>());
}
userTags.get("user123").add("premium");


==> В Apache Commons Collections уже давно есть готовая штука: MultiValuedMap.

Что это такое

MultiValuedMap<K, V> это структура данных, которая позволяет хранить несколько значений на один ключ. По сути это Map<K, Collection<V>>, но с нормальным, удобным API.

MultiValuedMap<String, String> userTags = new ArrayListValuedHashMap<>();

userTags.put("user123", "premium");
userTags.put("user123", "verified");
userTags.put("user123", "early-adopter");

// Забрать все теги сразу
Collection<String> tags = userTags.get("user123");
// [premium, verified, early-adopter]


Никаких computeIfAbsent, никаких проверок на null. Просто работает.

Что умеет

- Добавление без боли:

multiMap.put("key", "value1");
multiMap.put("key", "value2"); // не затирает предыдущее значение


- Массовые операции:

multiMap.putAll("user456", Arrays.asList("admin", "moderator"));


- Проверка существования конкретной пары:

multiMap.containsMapping("user123", "premium"); // true/false


- Удаление конкретного значения у ключа:

multiMap.removeMapping("user123", "premium");


- Получить вообще все значения:

Collection<String> allTags = multiMap.values();
// все значения со всех ключей


Реализации

- ArrayListValuedHashMap<K, V> — значения хранятся в ArrayList, порядок сохраняется, дубликаты возможны
- HashSetValuedHashMap<K, V> — значения хранятся в HashSet, без дублей

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Тестируете JBoss или другие Java application servers? 🧐

JexBoss это Python-инструмент для проверки серверов JBoss на известные уязвимости, включая проблемы с Java deserialization в ряде фреймворков (JSF, Seam, Jenkins, Struts2 и др.). Есть режим автопроверки сетей (скан диапазонов CIDR) для инвентаризации и поиска потенциально уязвимых узлов.

https://github.com/joaomatosf/jexboss

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Вопрос для интервью по Spring Boot:

Когда ты делаешь REST API в Spring Boot, часто используют префикс /api для всех контроллеров.
Но добавлять @RequestMapping("/api") в каждый контроллер неудобно и захламляет код.

Есть ли способ проще, чтобы не писать это на каждом контроллере?

Да: можно задать единый префикс через конфигурацию.

@Configuration
class WebMvcConfig implements WebMvcConfigurer {

@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("/api",
aClass -> aClass.getPackage().getName()
.startsWith("com.sivalabs.bookstore"));
}
}


Так ты автоматически добавляешь /api ко всем контроллерам из нужного пакета, а код контроллеров остается чистым.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

🔥 Пожизненная PRO-подписка на easyoffer по цене одного года.

Беспрецедентная акция на PRO-тариф сайта для подготовки к собеседованию на программиста, тестировщика, проектного менеджера и другие IT-профессии.

⚙️ Доступные функции сейчас:
1. База вопросов из реальных технических собеседований с вероятностью встречи и примерами ответов.
2. База задач с этапа live-coding.
3. База 1100+ реальных собеседований, в том числе в топовые компании (Сбер, Авито, Яндекс, WB, OZON, МТС и др.) на позиции Junior/Middle/Senior.
4. База 400+ тестовых заданий от компаний.
5. Аналитика ТОП-требований из вакансий для лучшего написания резюме по ключевым словам.
6. Тренажеры для подготовки к собеседованию. В том числе тренажер «Реальное собеседование» со сценарием вопросов под конкретную компанию.

⌛️ Функции, которые появятся в ближайшие полгода:
1. Агрегатор вакансий из Telegram, сайтов компаний и джоббордов.
2. Улучшение и оптимизация резюме, чтобы проходить ATS-системы.
3. Генерация уникального резюме и сопроводительного письма под вакансию.

Акция до 20 февраля (включительно) на PRO-тариф. Покупаешь сейчас один раз — пользуешься всю жизнь без лимита, включая все будущие функции.

👉 Смотри подробности тарифа и покупай на easyoffer

Читать полностью…

Java Portal | Программирование

java.evolved это подборка, где каждый старый паттерн из Java показан рядом с его современным заменителем, прямо бок о бок.

👍👍👍

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Какой SQL-запрос будет выполнен при вызове метода findByEmail()?

1. SELECT * FROM users WHERE email LIKE ?

2. SELECT id, name, email FROM users WHERE email LIKE ?

3. SELECT * FROM users WHERE email = ? LIMIT 1

4. SELECT * FROM users WHERE email = ?

5. SELECT * FROM users WHERE email = email

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Вопрос для собеседования по Spring Boot:

Какой будет результат запуска, если активный профиль не указан?

❓ Spring по умолчанию выберет бин DevNotificationService
❓ Spring выберет первый бин в алфавитном порядке
❓ Приложение упадет с NoSuchBeanDefinitionException
❓ Бины не будут созданы, но приложение запустится
❓ Будут созданы оба бина - NoUniqueBeanDefinitionException

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Как прогревать кэши в Spring Boot?

И вообще, как делать что-то на старте приложения?

Обычно такие операции делают в @PostConstruct или ловят событие ApplicationReadyEvent. Но у этих вариантов есть заметный минус.

Если “прогрев” лежит в @PostConstruct, как его отключать в тестах? Можно завести флаг, сделать наследника и подменять бин в тестовой конфигурации, но это не всегда помогает и часто выглядит как костыль.

Покажу более элегантный способ “прогрева кэшей”. В какой-то момент точно пригодится.

Смотри: SpringApplication.run(...) возвращает полностью готовый контекст. Из него можно получить нужный компонент и вызвать метод “прогрева”. Код выглядит так:

@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(MainApplication.class, args);
AccountService accService = ctx.getBean(AccountService.class);
accService.loadDictionary();
}
}


В чём плюс?

В интеграционных тестах с @SpringBootTest метод main не запускается. Значит, код внутри не выполняется. Никаких костылей вокруг @PostConstruct, всё чисто и аккуратно.

Когда всё-таки нужно, чтобы “прогрев” выполнялся и в тестах, добавь параметр “использовать main метод”:

@SpringBootTest(useMainMethod = SpringBootTest.UseMainMethod.ALWAYS)


И всё. Если код должен выполняться после старта, но мешает тестам, клади его в main. Очень полезный приём.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

...Script


👉 Java Portal

Читать полностью…

Java Portal | Программирование

Совет по Java: используйте Collectors.groupingBy(...), чтобы группировать результаты стрима по классификатору.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Твоя база данных не медленная.
Медленный у тебя цикл обратной связи.

Один сеньор написал практический гайд, где показано, как разработчику на Java анализировать производительность PostgreSQL из Quarkus-приложения с помощью pg_stat_statements, hypopg и PostgreSQL MCP-сервера через IBM Bob.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Развенчиваем распространенный миф про Java Garbage Collector

Миф: мне НЕ нужно заниматься управлением памятью в Java, потому что GC все делает за меня

Garbage Collector (GC) действительно очищает неиспользуемые объекты, на которые больше нет активных ссылок. Благодаря этому в Java не нужно вручную освобождать память, как в C++.

Несколько предпосылок, из которых обычно рождается этот тезис:

- В языках с ручным управлением памятью (C, C++) утечки очевидны: если забыл вызвать free(), память потеряна навсегда.
- В Java GC работает автоматически, поэтому кажется, что он сам решает все проблемы.
- «Ну раз есть GC, значит о памяти можно больше не думать» - типичная ошибка.

GC удаляет только те объекты, на которые больше нет активных ссылок. Если объект остается доступным, но фактически уже не используется, он будет занимать память до завершения приложения.

* Несколько случаев утечек памяти

[1] Статические коллекции (заполняем, но не очищаем)

Если создать static List и постоянно добавлять в него объекты, GC их никогда не освободит, потому что статические поля живут в течение всего времени работы приложения.

public class MemoryLeak {
private static final List<byte[]> cache = new ArrayList<>();
public static void main(String[] args) {
while (true) {
cache.add(new byte[10 * 1024 * 1024]);
System.out.println("Added 10MB to the cache. Used memory: " +
(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024) + "MB");
}
}
}


Через пару минут - OutOfMemoryError.

[2] Переменные потока (ThreadLocal)

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

public class ThreadLocalLeak {

private static final ThreadLocal<byte[]> threadLocalData = new ThreadLocal<>();
public static void main(String[] args) {

ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {

executor.execute(() -> {
threadLocalData.set(new byte[10 * 1024 * 1024]); // 10MB per thread
System.out.println("Memory occupied by the thread!");
});
}
executor.shutdown();

}
}


Поток завершится, но память останется занятой, потому что ThreadLocal не очищается автоматически.

[3] Внутренние классы и «утекшие» ссылки

Если анонимный класс или lambda-ссылка захватывает внешний объект, это может мешать GC освободить его.

public class InnerClassLeak {

private String data = "Very important data";
public void createAnonymousClass() {

Runnable task = new Runnable() {

@Override

public void run() {
System.out.println("Using: " + data);
}
};
new Thread(task).start();
}
}


task держит ссылку на data, и даже если InnerClassLeak больше не используется, GC не сможет очистить объект.

Миф развенчан. GC не всесилен, и даже с ним придется учиться правильно работать с памятью в Java.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

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

✅ В records можно иметь конструкторы, статические методы и методы экземпляра:

public record Email(String address) {

// Конструктор с валидацией
public Email {
if (address == null || !address.matches("^[\\w-.]+@([\\w-]+\\.)+[\\w-]{2,4}$")) {
throw new IllegalArgumentException("Некорректный email-адрес: " + address);
}
}

// Метод экземпляра
public String domain() {
return address.substring(address.indexOf('@') + 1);
}

// Статический метод
public static Email from(String raw) {
return new Email(raw.trim().toLowerCase());
}
}



👉 Java Portal

Читать полностью…

Java Portal | Программирование

Брейкпоинты в IDEA (IntelliJ и другие) для разработчиков

Иногда смотрю, как люди дебажат, и чуть ли не ловлю инсульт 🍺

Большинство разработчиков умеют только ставить и удалять брейкпоинты. А в IDEA есть куча полезных фич для отладки. Ниже самые годные:

[1] Условие остановки

Если метод вызывается часто или брейкпоинт стоит в цикле, не трать время, ожидая нужных значений:

▪️ПКМ по брейкпоинту
▪️В Condition добавь условие остановки. Можно использовать все доступные переменные, объекты и методы

[2] Динамически смотреть значения параметров

Вариант для новичков: добавить в код System.out.println с нужным полем/выражением.

Вариант для продвинутых:

▪️Зажми Shift и поставь брейкпоинт
▪️Отметь чекбокс Evaluate and log
▪️Введи нужное выражение

Дебаггер не будет останавливать выполнение, но будет писать значение выражения в консоль. Супер полезно для многопоточки, кода сторонних библиотек и remote debugging.

[3] Отключение брейкпоинта

Ненужный брейкпоинт можно не удалять, а просто выключить:

▪️Нажми на шестеренку у брейкпоинта
ИЛИ
▪️ПКМ по брейкпоинту → снимай галочку Enabled

[4] Массовая чистка

Когда в проекте много брейкпоинтов, IDE может чуть тормозить во время дебага. Чтобы убрать лишние, открой полный список:
▪️ПКМ по любому брейкпоинту
▪️Link More
▪️Слева будет список брейкпоинтов
▪️Удаляй ненужные

Обязательно попробуй. Пусть дебаг будет как по маслу 👍

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Java Collections Framework

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Какой будет результат выполнения кода?

→ {"name":"Laptop"}
→ {"name":"Laptop","price":50000}
→ {"price":50000}
→ {}
→ Ошибка компиляции

Примечание: по умолчанию при сериализации/десериализации Jackson опирается на спецификацию JavaBeans, то есть учитываются только методы getter и setter.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Java Stream API Evolution (с Java 8 до Java 21).

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Spring Boot: Используй ResponseEntity<T>, чтобы получить тонкий контроль над HTTP-ответом.

Можно явно задать status, headers и body.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Совет по Spring Boot: если тебе нужны интеграционные тесты для контроллеров Spring MVC, а всё остальное ты хочешь замокать, используй @WebMvcTest — он поднимет только MVC-бины (контроллеры, конфиг MVC, конвертеры, валидацию и т.п.), без полного контекста приложения.

▪️Он грузит только MVC-бины, а не весь application context целиком.

▪️Интеграционные тесты медленнее юнитов, поэтому их стоит ускорять, выкидывая все лишнее, что не нужно конкретно для MVC.

▪️В этом примере мы мокaем бин HelloService и поднимаем только MVC-контекст и сам контроллер:

@WebMvcTest(HelloController.class)
class HelloControllerTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private HelloService helloService; // замокано

@Test
void sayHello_returnsExpectedMessage() throws Exception {
given(helloService.getMessage()).willReturn("Hello!");
mockMvc.perform(get("/api/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello!"));
}
}


👉 Java Portal

Читать полностью…

Java Portal | Программирование

Spring Boot: используй @SpringBootApplication(exclude = …), чтобы отключить конкретные классы автоконфигурации.

✅ Одна из возможных причин: кастомная конфигурация конфликтует с дефолтной.

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Java tip : старайся не шарить данные между потоками.

✅Используй иммутабельные объекты
✅Либо пусть потоки общаются через сообщения, не трогая общий state напрямую и не мутируя shared-состояние

// С иммутабельными объектами:

record Book(String title, int price) {} // Иммутабельный

public class BookJob implements Runnable {
private final Book book;
.... // конструктор

@Override
public void run() {
System.out.println(book.title() + " " + book.price());
}
}

// Обмен сообщениями:

...
new Thread(() -> {
try {
queue.put("mess1");
} catch (InterruptedException e) {}
}).start();

...
new Thread(() -> {
try {
String mess = queue.take();
} catch (InterruptedException e) {}
}).start();


👉 Java Portal

Читать полностью…

Java Portal | Программирование

Spring Boot: можно использовать @Retryable, чтобы переживать нестабильность внешних сервисов.

@Service
public class ExtService {

@Retryable(
value = { HttpServerErrorException.class, ResourceAccessException.class },
maxAttempts = 3,
backoff = @Backoff(delay = 2000, multiplier = 2)
)
public ExtServiceResponse process(ExtServiceRequest request) {
// Call external payment gateway
return restTemplate.postForObject("https://ext-gateway/api/service", request,
ExtServiceResponse.class);
}

@Recover
public ExtServiceResponse recover(Exception e, ExtServiceRequest request) {
// Fallback logic after retries are exhausted
log.error("Failed after retries: {}", e.getMessage());
return new ExtServiceResponse("FAILED");
}
}


Что это делает:

▪️Делает 3 ретрая, если вылетают указанные исключения.
▪️Стартует с задержки 2 секунды и удваивает ее на каждой попытке (экспоненциальный backoff).
▪️Если все попытки провалились, вызывает recover().

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Java-совет: чтобы не ловить оверхед на boxing/unboxing, используй стримы примитивов (IntStream/LongStream/DoubleStream) вместо Stream<Integer>/Stream<Long>/Stream<Double>.

❌Создаём объекты Integer для каждого значения:

Stream<Integer> boxed = Stream.of(1, 2, 3, 4, 5);
int sumBoxed = boxed.reduce(0, Integer::sum);


✅Работаем напрямую с int:

int sumPrimitive = IntStream.of(1, 2, 3, 4, 5).sum();


✅Другие примитивные стримы:

LongStream, DoubleStream

👉 Java Portal

Читать полностью…

Java Portal | Программирование

Большинство разработчиков в Spring знают, как доставать query-параметры и path variables.

Но часто забывают, что HTTP-хедеры можно вытаскивать так же просто. В Spring для этого есть аккуратный @RequestHeader.

Можно в одну строку получить User-Agent, Authorization или любой кастомный хедер. И не нужно лезть в HttpServletRequest.

Пример:

▪️Добавляешь в метод контроллера @RequestHeader("User-Agent") String userAgent
▪️Spring сам подхватывает значение из заголовка
▪️Ты получаешь его сразу параметром метода

Нужно сделать опциональным?
Просто добавь required = false.

Нужен дефолт?

▪️Используй defaultValue = "unknown".
▪️Очень полезно для логирования, аналитики, A/B тестов или фичефлагов, завязанных на заголовки.
▪️Выручает при работе с API-клиентами, которые шлют кастомные заголовки.
▪️Чище, короче и легче тестируется.
▪️Чем меньше зависимостей от servlet API, тем лучше.

👉 Java Portal

Читать полностью…
Subscribe to a channel