⚠️ Чем опасен Scheduled(fixedRate) без Transactional в Spring?
Многие используют
👎 Проблема:
Если метод выполняется дольше, чем интервал
Результат — дублирование обработки, гонки, порча данных.
Пример:
💥 Через 10 секунд начнёт работать следующий вызов, даже если первый ещё не закончен.
✅ Решение: обернуть в @Transactional и использовать блокировки:
📌 Также можно:
— использовать fixedDelay вместо fixedRate — он ждёт окончания предыдущей задачи
— добавить флаг locked, чтобы явно помечать уже взятые задачи
— заменить @Scheduled на более надёжные инструменты:
🟢 Spring Batch — для сложных задач
🟢 Spring Integration / Camunda — если нужны гарантии и retry
🟢 Quartz — если важны очередь и контроль запуска
🔧 Не упирайтесь в @Scheduled, если задача критична к повторной обработке.
✅ Java библиотека #java
Многие используют
@Scheduled для запуска задач по таймеру, но забывают об одной критичной вещи — транзакциях. Особенно если указан fixedRate.👎 Проблема:
Если метод выполняется дольше, чем интервал
fixedRate, запускается второй поток, который снова возьмёт те же данные. Результат — дублирование обработки, гонки, порча данных.
Пример:
@Scheduled(fixedRate = 10_000)
public void cleanUp() {
List<Job> jobs = jobRepository.findAllByStatus(PENDING);
jobs.forEach(job -> {
job.setStatus(PROCESSING);
jobRepository.save(job);
});
}
💥 Через 10 секунд начнёт работать следующий вызов, даже если первый ещё не закончен.
✅ Решение: обернуть в @Transactional и использовать блокировки:
@Transactional
@Scheduled(fixedRate = 10_000)
public void cleanUp() {
List<Job> jobs = jobRepository.findAllByStatusForUpdate(PENDING);
...
}
📌 Также можно:
— использовать fixedDelay вместо fixedRate — он ждёт окончания предыдущей задачи
— добавить флаг locked, чтобы явно помечать уже взятые задачи
— заменить @Scheduled на более надёжные инструменты:
🔧 Не упирайтесь в @Scheduled, если задача критична к повторной обработке.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍8🔥5😁1
Когда нужно аккуратно скопировать блок кода, метод, выражение или просто цепочку вызовов — забудьте про мышь. У IntelliJ есть инструмент поумнее.
Хоткей: Ctrl + W (или Cmd + W на macOS)
По нажатии IDEA «расширяет» выделение:
— сначала слово,
— потом выражение,
— затем строку целиком,
— потом блок кода,
— и так до всего метода или класса.
— Быстро выделить логически связанный фрагмент без лишней возни.
— Удобно вырезать или перемещать части кода.
— Работает даже внутри строк, SQL-запросов, JSON и XML.
— Поставьте курсор в нужное место.
— Нажимайте Ctrl + W по очереди — и наблюдайте, как IDEA понимает структуру кода.
— Ctrl + Shift + W — отменяет шаг назад.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥15❤4
🧱 Maven vs. ⚡️Gradle — что выбрать разработчику?
Когда речь заходит о сборке Java-проектов, чаще всего выбор стоит между двумя фреймворками: Maven и Gradle. Оба стали стандартом в индустрии, но у каждого — свои сильные и слабые стороны. Разбираем, кому что подойдёт 👇
🟢 Maven — стабильная классика:
✅ Строгая структура: легко читать и сопровождать
✅ Надёжность и предсказуемость сборки
✅ Много плагинов и готовых решений
⚠️ XML-конфигурация громоздкая
⚠️ Медленнее по сравнению с Gradle
🟡 Gradle — гибкость и скорость:
✅ Поддержка Kotlin и Groovy DSL
✅ Инкрементальные сборки и кэширование
✅ Гибкий подход к конфигурации
⚠️ Порог входа выше
⚠️ Сложности с отладкой настроек
📌 Вывод:
🟢 Выбирай Maven, если важны стабильность, читаемость и простота
🟡 Выбирай Gradle, если хочешь максимум производительности и гибкости
💬 В крупных проектах Gradle становится всё популярнее, особенно с Kotlin.
Но в enterprise-среде Maven по-прежнему остаётся стандартом.
А ты чем пользуешься? Делись в комментариях👇
✅ Java библиотека #java
Когда речь заходит о сборке Java-проектов, чаще всего выбор стоит между двумя фреймворками: Maven и Gradle. Оба стали стандартом в индустрии, но у каждого — свои сильные и слабые стороны. Разбираем, кому что подойдёт 👇
✅ Строгая структура: легко читать и сопровождать
✅ Надёжность и предсказуемость сборки
✅ Много плагинов и готовых решений
⚠️ XML-конфигурация громоздкая
⚠️ Медленнее по сравнению с Gradle
✅ Поддержка Kotlin и Groovy DSL
✅ Инкрементальные сборки и кэширование
✅ Гибкий подход к конфигурации
⚠️ Порог входа выше
⚠️ Сложности с отладкой настроек
💬 В крупных проектах Gradle становится всё популярнее, особенно с Kotlin.
Но в enterprise-среде Maven по-прежнему остаётся стандартом.
А ты чем пользуешься? Делись в комментариях
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍4🔥3
Нужно быстро развернуть REST API c валидацией, логированием, DTO, безопасностью и документацией?
AI справится с этим за один промпт — код будет готов к продакшну, с учетом архитектурных паттернов.
📝 Промпт:
Generate a Spring Boot REST API for managing [сущность или бизнес-логика, например: product catalog, user profiles, task assignments].
Include CRUD endpoints, validation (Hibernate Validator), exception handling, DTO mapping (MapStruct or ModelMapper), and OpenAPI documentation.
Ensure security with JWT-based authentication and role-based access control (Spring Security).
Use layered architecture (Controller → Service → Repository) and follow clean code principles. Add unit tests for controller and service layers.
— Добавьте
integrate with PostgreSQL using Spring Data JPA and specify indexes/constraints для подключения к БД.— Добавьте
support pagination and filtering with Pageable and Specification API для удобных выборок.— Добавьте
plug into CI/CD pipeline with Docker and GitHub Actions для продвинутого автодеплоя.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤7👍5😁1
Представьте, что вы пишете in-memory кеш конфигураций. У вас есть
ConfigService, который должен:loadConfigFromDB()) 🔧 Что нужно сделать:
Реализуйте
ConfigService, который использует AtomicReference<Config> и Immutable-объекты, чтобы:1. Конфигурация всегда была консистентной
2. Потоки не блокировали друг друга
3. Обновления конфигурации были моментальными и безопасными
📦 Пример API:
class ConfigService {
public Config getCurrentConfig(); // read-only, вызывается часто
public void reload(); // обновить конфиг, редко
}
🧠 Хитрость: нельзя использовать synchronized, volatile массивы, CopyOnWrite, ReentrantLock, и т.п. — только атомарность и неизменяемость.
🚀 Challenge accepted?
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤6👍6
Java Совет 🖥
Как понять, что Java‑код мог быть сгенерирован ИИ?
🟢 Если вы видите в коде
А
📌 Документация
✅ Java библиотека #java
Как понять, что Java‑код мог быть сгенерирован ИИ?
Collectors.toList(), а не Stream.toList() — это явный намёк 😉Stream.toList() появился только в Java 16. А
Collectors.toList() — с нами ещё с Java 8, поэтому его до сих пор полно в туториалах, на Stack Overflow и во всех датасетах, на которых обучают ИИ.Please open Telegram to view this post
VIEW IN TELEGRAM
😁18👍6❤5🔥4🎉1
Forwarded from Java Guru 🤓
Что будет результатом кода?
Anonymous Quiz
30%
10 11 12
18%
20 21 22
22%
Ошибка компиляции
12%
ConcurrentModificationException
18%
Непредсказуемый результат
👍15❤5🔥5
Ищете решение для построения масштабируемого микросервиса с использованием Event Sourcing и CQRS? AI поможет вам сгенерировать шаблон, который будет учитывать все архитектурные принципы и лучшие практики для сложных бизнес-логик.
📝 Промпт:
Generate a Spring Boot microservice that implements Event Sourcing and CQRS (Command Query Responsibility Segregation).
— Implement event storage (using EventStore or any other event-sourcing mechanism).
— Design the service layer using separate models for command and query operations.
— Use an event-driven approach with messaging (e.g., Kafka or RabbitMQ) to communicate between services.
— Secure the API with JWT authentication and role-based access control (Spring Security).
— Implement database persistence for event snapshots and projections (using Spring Data JPA).
— Добавьте
support asynchronous messaging with Kafka or RabbitMQ для обработки событий между микросервисами.— Добавьте
implement Command and Query models using CQRS для разделения логики записи и чтения данных.— Добавьте
integrate snapshotting mechanism for efficient aggregate recovery и управление состоянием событий.— Добавьте
enable monitoring and tracing with Spring Actuator and Zipkin для отслеживания производительности и запросов.Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥3
Задача:
Предположим, вы пишете сервис, в котором создаются задачи (например, отложенные действия):
public class TaskScheduler {
private final List<Runnable> tasks = new ArrayList<>();
public void scheduleTask(String name) {
String largeData = name.repeat(10_000); // имитируем большой объект
tasks.add(() -> {
System.out.println("Running task: " + name);
});
}
public void runAll() {
tasks.forEach(Runnable::run);
}
}
Теперь создайте 1_000_000 таких задач:
TaskScheduler scheduler = new TaskScheduler();
for (int i = 0; i < 1_000_000; i++) {
scheduler.scheduleTask("Task" + i);
}
Вопрос:
Почему
String largeData не освобождается сборщиком мусора, хотя он нигде явно не используется?Разбор:
На первый взгляд,
largeData нигде не используется — его можно было бы освободить. Но на самом деле лямбда-захват переменной
name удерживает весь стек метода scheduleTask, включая largeData.Это называется неявная утечка памяти через замыкания.
---
Как исправить?
Чтобы избежать утечки, выносите только нужные значения в лямбду:
public void scheduleTask(String name) {
String taskName = name; // только то, что действительно нужно
tasks.add(() -> {
System.out.println("Running task: " + taskName);
});
}
Или даже:
tasks.add(() -> System.out.println("Running task: " + name));
НО! Убедитесь, что переменные вне лямбды не держат в памяти тяжёлые объекты, которые не нужны после исполнения.
💡 Вывод:
- Java лямбды могут неявно захватывать контекст, включая большие объекты
- Это может привести к утечкам памяти, особенно в long-lived объектах (пулы задач, слушатели и т.п.)
- Профилируйте и проверяйте, что захватывает ваша лямбда
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👍8❤6
Для улучшения безопасности вашего приложения можно настроить фильтрацию запросов с использованием Spring Security, а также внедрить блокировку определённых IP-адресов.
В файл pom.xml добавьте следующие зависимости:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Создайте фильтр, который будет проверять IP-адрес пользователя и блокировать его, если он находится в списке запрещённых:
@Component
public class IpFilter extends OncePerRequestFilter {
private static final Set<String> blockedIps = new HashSet<>(Arrays.asList("192.168.1.100", "10.0.0.5"));
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String ipAddress = request.getRemoteAddr();
if (blockedIps.contains(ipAddress)) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.getWriter().write("Access Denied: Your IP is blocked.");
return;
}
filterChain.doFilter(request, response);
}
}
Теперь настроим Spring Security, чтобы наш фильтр IP-блокировки применялся ко всем входящим запросам:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private IpFilter ipFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/public/**").permitAll() // Доступ для публичных ресурсов
.anyRequest().authenticated() // Остальные запросы требуют аутентификации
.and()
.addFilterBefore(ipFilter, UsernamePasswordAuthenticationFilter.class); // Вставляем фильтр IP
}
}
Создадим простой контроллер с двумя маршрутами: один доступен всем пользователям, а другой требует аутентификации:
@RestController
public class TestController {
@GetMapping("/public/hello")
public String publicHello() {
return "Hello from public endpoint!";
}
@GetMapping("/private/hello")
public String privateHello() {
return "Hello from private endpoint, you are authenticated!";
}
}
Этот подход не является универсальной защитой от всех типов атак. Он помогает ограничить доступ для определённых IP-адресов, но не защищает от более сложных угроз, таких как атаки с подменой IP (например, через прокси-серверы).
Для более комплексной защиты используйте дополнительные механизмы, такие как WAF, анти-DDoS системы, а также более детальную настройку доступа через роли и права.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥5❤3
Представьте, что вы пишете in-memory кеш конфигураций. У вас есть
ConfigService, который должен:loadConfigFromDB()) 🔧 Что нужно сделать:
Реализуйте
ConfigService, который использует AtomicReference<Config> и Immutable-объекты, чтобы:1. Конфигурация всегда была консистентной
2. Потоки не блокировали друг друга
3. Обновления конфигурации были моментальными и безопасными
📦 Пример API:
class ConfigService {
public Config getCurrentConfig(); // read-only, вызывается часто
public void reload(); // обновить конфиг, редко
}
🧠 Хитрость: нельзя использовать synchronized, volatile массивы, CopyOnWrite, ReentrantLock, и т.п. — только атомарность и неизменяемость.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤3🔥3
Если обычный поиск по проекту вам тесен — попробуйте Structural Search and Replace (SSR). Это инструмент, который ищет и меняет код не по тексту, а по его структуре — как настоящий парсер.
Находит шаблоны кода в проекте с учётом синтаксиса языка. Можно искать любые конструкции — например, все System.out.println или пустые catch блоки — и сразу массово их переписывать.
— Автоматически находить антипаттерны.
— Глобально рефакторить одинаковые места.
— Быстро готовить проект к миграции или внедрению новых стандартов кодирования.
— Откройте Edit → Find → Search Structurally или нажмите Shift + Shift и введите Structural Search.
— Задайте шаблон — например, System.out.println($arg$);.
— IDEA выделит все совпадения по всей кодовой базе.
— Для массовой замены найдите в поиске Replace Structurally — можно указать новый шаблон, и IDEA всё подставит сама.
— Шаблоны можно сохранять и делиться ими с командой.
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥14👍12❤5
🌐 dnsjava — DNS-клиент и сервер на Java. Эта библиотека предлагает полную реализацию DNS-протокола с поддержкой современных стандартов — от DNSSEC и EDNS0 до TSIG-аутентификации. Проект позволяет не только выполнять запросы, но и организовывать трансфер зон, динамические обновления и даже разворачивать авторитативный сервер.
Инструмент имеет встроенный механизм валидации DNSSEC через
🖥 GitHub
✅ Java библиотека #java
Инструмент имеет встроенный механизм валидации DNSSEC через
ValidatingResolver и гибкая система конфигурации через системные свойства. Поддерживает Java 8+ и может заменять стандартный DNS-резолвер JVM. Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍4🔥2
Работаете с микросервисной архитектурой? Тогда знаете, как сложно обеспечить стабильные API-контракты между сервисами. Contract Testing решает эту проблему. А AI поможет быстро сгенерировать заготовку всей инфраструктуры для автоматизированной валидации контрактов.
📝 Промпт:
Generate a Java Spring Boot setup for contract testing using Spring Cloud Contract and Testcontainers.
— Configure a provider service and a consumer service.
— Use Spring Cloud Contract to define and verify contracts.
— Integrate with Testcontainers to run provider stubs in isolated environments.
— Add Gradle or Maven setup for running contract tests in CI.
— Provide examples for both producer and consumer side tests.
— Добавьте
integration with GitLab CI/CD or GitHub Actions для автоматической валидации контрактов при push'ах и pull request'ах.— Добавьте
generate stub JARs using Spring Cloud Contract Verifier для повторного использования контрактов на стороне потребителя.— Добавьте
handle contract mismatches gracefully with test reports and logs для быстрого выявления расхождений между сервисами и прозрачной отладки в CI.— Добавьте
include real-world example: REST endpoint for user profile with request validation and response structure как шаблон, который можно адаптировать под любую бизнес-логику.Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤3🔥2
🚀 Хочешь быстро разобраться, как использовать GraphQL с Spring Boot?
📦 Репозиторий содержит набор готовых микросервисов на Spring Boot, каждый из которых показывает разные аспекты интеграции с GraphQL: от простых запросов до работы с subnoscriptions и federated схемами.
Что внутри:
- 📌 Примеры с использованием Spring Boot 3 и GraphQL Java
- 🔗 Демонстрация схемы Federation с Apollo Gateway
- ☁️ Микросервисная архитектура + Docker Compose
- ⚙️ Использование Spring Data и JPA с GraphQL
- 🔄 Примеры запросов и мутаций через GraphiQL
Полезно как для новичков в GraphQL, так и для разработчиков, строящих продвинутые API на Spring Boot. Всё собрано и работает из коробки.
🖥 Репозиторий
📦 Репозиторий содержит набор готовых микросервисов на Spring Boot, каждый из которых показывает разные аспекты интеграции с GraphQL: от простых запросов до работы с subnoscriptions и federated схемами.
Что внутри:
- 📌 Примеры с использованием Spring Boot 3 и GraphQL Java
- 🔗 Демонстрация схемы Federation с Apollo Gateway
- ☁️ Микросервисная архитектура + Docker Compose
- ⚙️ Использование Spring Data и JPA с GraphQL
- 🔄 Примеры запросов и мутаций через GraphiQL
Полезно как для новичков в GraphQL, так и для разработчиков, строящих продвинутые API на Spring Boot. Всё собрано и работает из коробки.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2🔥1
Если вы часто просматриваете стек вызовов или трассируете поведение методов — попробуйте «Call Hierarchy» (Ctrl + Alt + H). Этот инструмент показывает, кто вызывает ваш метод — и кто вызывает вызывающего, до самого верхнего уровня.
— Строит иерархию вызовов метода вверх или вниз.
— Помогает отследить влияние метода по всей кодовой базе.
— Работает даже с интерфейсами и абстрактными методами — покажет всех наследников.
— Находит неочевидные связи между частями кода.
— Упрощает работу с легаси: видно, какие методы безопасно менять.
— Быстро определяет, как ошибка «долетела» до нужного места.
— Поставьте курсор на метод → нажмите Ctrl + Alt + H.
— IDEA откроет дерево вызовов (Call Hierarchy).
— Вы можете «разворачивать» цепочку вверх по стеку или вниз.
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍20🔥3❤2
Проект сочетает desktop-приложение для визуальной работы и Kotlin Multiplatform библиотеку для программного взаимодействия с class-файлами. Поддерживает работу с JAR-архивами, предлагает темную тему и локализации на несколько языков.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8❤3👍2
Forwarded from Java Guru 🤓
Что будет результатом инжекта бина А?
Anonymous Quiz
18%
Выведутся сообщения: Ainitialized B initialized
7%
Приложение запустится, но "а" в В останется null.
46%
BeanCurrentlyInCreationException
5%
Будет создан только бин А
23%
Ошибка компиляции
👍7❤6🔥2