TGViewer
Channel Public Channel
Библиотека джависта | Java, Spring, Maven, Hibernate

Библиотека джависта | Java, Spring, Maven, Hibernate

@javaproglib

Все самое полезное для Java-разработчика в одном канале.

Учиться у нас: clc.to/AATM8w

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

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

РКН: https://gosuslugi.ru/snet/67a5bbda1b17b35b6c1a55c4
Subscribers
22K
Photos
2.5K
Videos
57
Links
3.7K

Showing posts older than #7495 · Back to latest

Older Posts 20 shown
Post #7494 2.4K
🔧 Spring Retry: повторные попытки с backoff без ручных циклов

Retry-логика руками — источник багов. Неправильный backoff создаёт thundering herd. Spring Retry решает это декларативно.

🔹 Решение

▪️ Зависимость

<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>


▪️ Включение и базовое использование

@Configuration
@EnableRetry
public class RetryConfig { }

@Service
public class ExternalApiService {

@Retryable(
retryFor = {IOException.class, HttpServerErrorException.class},
noRetryFor = {HttpClientErrorException.class}, // 4xx не ретраим
maxAttempts = 4,
backoff = @Backoff(
delay = 1000,
multiplier = 2,
maxDelay = 10000,
random = true // jitter для предотвращения thundering herd
)
)
public ApiResponse callExternalApi(ApiRequest request) {
return restClient.post()
.uri("/api/endpoint")
.body(request)
.retrieve()
.body(ApiResponse.class);
}

@Recover
public ApiResponse recover(IOException e, ApiRequest request) {
log.error("All retry attempts exhausted for request: {}", request.getId(), e);
// fallback логика или выброс бизнес-исключения
throw new ExternalServiceUnavailableException(request.getId(), e);
}
}


▪️ Программная конфигурация для сложных случаев

@Bean
public RetryTemplate retryTemplate() {
return RetryTemplate.builder()
.maxAttempts(5)
.exponentialBackoff(1000, 2, 30000)
.retryOn(IOException.class)
.withListener(new RetryListenerSupport() {
@Override
public <T, E extends Throwable> void onError(RetryContext ctx,
RetryCallback<T, E> cb,
Throwable t) {
log.warn("Retry attempt {} failed: {}",
ctx.getRetryCount(), t.getMessage());
}
})
.build();
}


▪️ Интеграция с Circuit Breaker


@CircuitBreaker(name = "externalApi", fallbackMethod = "circuitFallback")
@Retryable(retryFor = IOException.class, maxAttempts = 3)
public ApiResponse callWithProtection(ApiRequest request) {
return callExternalApi(request);
}


Retry отрабатывает до Circuit Breaker. Ошибки после всех попыток засчитываются как один сбой в Circuit Breaker — корректное поведение.

random = true в @Backoff добавляет jitter — случайное смещение задержки. Без jitter все инстансы приложения, получившие ошибку одновременно, будут ретраить синхронно, создавая пики нагрузки на восстанавливающийся сервис. Jitter разбивает пики.

⚠️ Ретраить нужно только идемпотентные операции. POST с созданием ресурса без идемпотентного ключа при ретрае создаст дубликаты. Либо добавить Idempotency-Key заголовок, либо не ретраить.

══════ Навигация ══════
Вакансии • Задачи • Собесы

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

#Enterprise
  • ❤ 7
  • 👍 6
  • 🔥 1
Post #7493 2.56K
Самый востребованный навык в ИТ в 2026-м — навык создания ИИ-агентов

Мы полностью переработали курс «Разработка AI-агентов» под реалии 2026 года. Никакой долгой теории — с самого начала пишем код. Обучать и делиться набитыми шишками будут эксперты-практики из Газпромбанка, Альфа-Банка и других бигтехов.

В программе:

— архитектура автономных систем с тестированием, ReAct-циклами и контролем токенов;
— практическая работа с актуальными фреймворками LangGraph, AutoGen, MCP и CrewAI;
— настройка продвинутого RAG для парсинга документов и точного поиска;
— внедрение решений с учётом действующего законодательства (152-ФЗ);
— дипломная работа, за основу которой можно взять свой рабочий проект или задачу, которую предложим мы.

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

Запись первого открытого вебинара, на котором мы вместе с руководителем AI-направления в Альфа-Банке Полиной Полуниной пилили агента в прямом эфире.


Ах да, чуть не забыли! Дарим промокод AGENTSWEB на скидку 10 000 рублей и два курса сверху при покупке до 15 марта 🎁

→ Освоить разработку AI-агентов
  • 😁 2
  • ❤ 1
Post #7491 3.38K
🖥 На GitHub есть отличный репозиторий

resources-learning-spring — там собраны лучшие материалы для изучения Spring от команды Spring Office Hours. Репозиторий вырос из подкаст-эпизода, где авторы делились любимыми ресурсами, и с тех пор активно пополняется сообществом.

🔹 Внутри найдёте всё по категориям: официальная документация Spring Boot и Spring Framework, книги, YouTube-каналы, подкасты, блоги, конференции и живые GitHub-репозитории с примерами.

══════ Навигация ══════
Вакансии • Задачи • Собесы

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

#CoreJava
  • 👍 7
  • ❤ 4
  • 🔥 3
Post #7490 2.49K

Forwarded from Библиотека собеса по Java | вопросы с собеседований

❓ Объясните happens-before отношение в Java Memory Model?

happens-before — это гарантированный порядок между операциями, который определяет, что эффект одной операции виден другой. Если операция A happens-before операции B, то все изменения, сделанные в A, будут видны к моменту B.

Примеры гарантий happens-before: запись в volatile поле и последующее чтение того же поля; блокировки synchronized; Thread.start() и Thread.join().

Без гарантии happens-before два потока могут видеть неверные или устаревшие значения: один поток записал в поле, другой не увидит это изменение.

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

#concurrency
  • 👍 4
  • 🔥 4
  • ❤ 2
Post #7489 3.02K
🐳 Прокачай Docker CLI

Dockerlings предлагает более 15 упражнений, которые последовательно учат работать с контейнерами, Dockerfile, сетями, томами и многими другими важными аспектами Docker.

Главная особенность — это удобный интерфейс, который позволяющий выполнять задания и сразу же проверять свои решения.

🔗 Пробуй и тренируйся

══════ Навигация ══════
Вакансии • Задачи • Собесы

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

#Enterprise
  • 👍 10
  • ❤ 4
  • 🔥 2
  • 👏 1
Post #7488 2.69K
🔥 Java наконец-то избавляется от «налога на объект»

28 МБ для хранения миллиона точек вместо честных 8 — вот цена идентичности каждого объекта в JVM. Project Valhalla это исправляет.

Value Classes — и данные лежат в памяти плоско, как примитивы. Никаких заголовков, никакого pointer chasing, GC доволен.

🔗 Подробно с цифрами в статье
  • ❤ 7
  • 👍 5
  • 🔥 1
Post #7486 2.84K
🔍 BeanDefinition Pipeline

Spring ApplicationContext при старте проходит через чётко определённую последовательность фаз. Понимание этой последовательности объясняет, почему одни расширения работают, а другие нет, и почему порядок объявления бинов иногда имеет значение.

Фазы загрузки контекста

1️⃣ Загрузка BeanDefinition'ов

Контекст читает конфигурацию и строит реестр BeanDefinition. На этом этапе объекты ещё не создаются. BeanDefinition — это метаданные: класс, scope, зависимости, lazy/eager, init/destroy методы.

2️⃣ BeanFactoryPostProcessor

После того как все BeanDefinition загружены, но до создания каких-либо бинов, вызываются BeanFactoryPostProcessor. Они получают доступ к ConfigurableListableBeanFactory и могут модифицировать, добавлять или удалять BeanDefinition.

Самый известный пример — PropertySourcesPlaceholderConfigurer. Он резолвит ${...} плейсхолдеры в BeanDefinition прямо на этом этапе. Именно поэтому @Value("${some.property}") работает — к моменту создания бина значение уже подставлено в метаданные.

ConfigurationClassPostProcessor — ещё один критический BeanFactoryPostProcessor. Он обрабатывает @Configuration классы, @ComponentScan, @Import, регистрирует дополнительные BeanDefinition. Без него Spring Boot не работал бы.

⚠️ BeanFactoryPostProcessor сам является бином, но Spring создаёт его раньше остальных отдельным путём. Если BeanFactoryPostProcessor зависит от другого бина через @Autowired — этот бин будет создан раньше срока, до фазы BeanPostProcessor. Это ведёт к тому что аспекты и другие пост-процессоры не применяются к нему. Spring даже выводит предупреждение в лог в таких случаях.

3️⃣ Создание экземпляра и инициализация

Для каждого eager singleton:
— Создание инстанса через конструктор или фабричный метод.
— Внедрение зависимостей (setter injection, field injection).
— Вызов BeanPostProcessor.postProcessBeforeInitialization.
— Вызов init-метода (@PostConstruct → InitializingBean.afterPropertiesSet() → initMethod)
— Вызов BeanPostProcessor.postProcessAfterInitialization.

BeanPostProcessor — именно здесь работает Spring AOP. AbstractAutoProxyCreator реализует BeanPostProcessor и в postProcessAfterInitialization оборачивает бин в прокси если нужно.

4️⃣ SmartInitializingSingleton

После инициализации всех singleton-бинов Spring вызывает afterSingletonsInstantiated() на каждом бине, реализующем этот интерфейс. Полезно, когда нужно выполнить логику гарантированно после того, как все синглтоны готовы — в отличие от @PostConstruct, который срабатывает до завершения инициализации остальных бинов.

5️⃣ Публикация события ContextRefreshedEvent

После того как все бины готовы. ApplicationListener на этот ивент — стандартный способ выполнить логику после полного старта контекста.

🔹 Порядок BeanPostProcessor'ов

Порядок определяется через Ordered или PriorityOrdered. PriorityOrdered применяется раньше Ordered, Ordered раньше остальных. Внутри одного уровня по getOrder().

Это важно когда несколько BeanPostProcessor обрабатывают один бин: AOP-прокси, валидация, кастомный мониторинг. Неправильный порядок может привести к тому что один пост-процессор получит прокси вместо оригинального объекта или наоборот.

══════ Навигация ══════
Вакансии • Задачи • Собесы

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

#CoreJava
  • 👍 14
  • 🔥 4
  • 🤔 3
  • 🙏 2
Post #7482 2.4K
☝️ Уже сегодня: ИИ-агенты в продакшене — инженерный подход к интеграции LLM

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

Сегодня в 19:00 МСК в рамках нашего курса «Разработка AI-агентов» мы проведём открытый вебинар «ИИ-агенты в продакшене: от хайпа к деньгам». Спикер — Полина Полунина, руководитель AI-направления в Альфа-Банке. Будем говорить о нейросетях с позиции жёсткой инженерии.

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

Тем, кто придёт на эфир, дадим промокод AGENTS на скидку 10 000 ₽ на любой тариф курса.

👉 Занять место на вебинаре
Post #7479 2.38K
🌐 Как настроить Spring Cloud Gateway

Spring Cloud Gateway — это API Gateway поверх Project Reactor. Маршрутизация запросов, балансировка нагрузки, rate limiting, аутентификация.

Реактивный, non-blocking, легко расширяемый через фильтры.

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

Добавьте spring-cloud-starter-gateway — это вытащит Reactor Netty как сервер. Важно: НЕ добавляйте spring-boot-starter-web, они несовместимы. Gateway работает на WebFlux стеке.

Для service discovery добавьте spring-cloud-starter-netflix-eureka-client или spring-cloud-starter-consul-discovery.

2️⃣ Настраиваем маршруты через application.yml

spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://USER-SERVICE
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1


lb:// — это magic prefix для балансировки через service discovery. StripPrefix=1 срезает /api перед проксированием запроса вниз.

3️⃣ Пишем кастомный GlobalFilter

@Component
public class AuthFilter implements GlobalFilter, Ordered {

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest()
.getHeaders()
.getFirst(HttpHeaders.AUTHORIZATION);

if (token == null || !isValid(token)) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}

@Override
public int getOrder() { return -1; } // выполняется первым
}


getOrder() с отрицательным значением — фильтр выполнится до встроенных. Возвращайте chain.filter(exchange) чтобы пропустить запрос дальше.

4️⃣ Rate Limiting через Redis

filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@userKeyResolver}"

@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
);
}


replenishRate — токенов в секунду, burstCapacity — максимальный burst. Требует spring-boot-starter-data-redis-reactive.

5️⃣ Circuit Breaker с Resilience4j

filters:
- name: CircuitBreaker
args:
name: userServiceCB
fallbackUri: forward:/fallback/users

@RestController
public class FallbackController {
@GetMapping("/fallback/users")
public Mono<String> usersFallback() {
return Mono.just("Users service unavailable");
}
}


Circuit Breaker открывается при превышении порога ошибок и перенаправляет на fallback endpoint вместо каскадного падения.

6️⃣ Настраиваем CORS централизованно

@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*");
config.addAllowedMethod("*");
config.addAllowedHeader("*");

UrlBasedCorsConfigurationSource source =
new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}


Настраивайте CORS на уровне Gateway — не нужно дублировать это в каждом микросервисе.

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

Запрос приходит → RoutePredicateHandlerMapping матчит маршрут по predicates → цепочка GatewayFilter обрабатывает запрос → NettyRoutingFilter проксирует вниз → цепочка фильтров обрабатывает ответ в обратном порядке.

Всё это non-blocking на Project Reactor. Один поток может обрабатывать тысячи одновременных соединений.

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

Actuator endpoint /actuator/gateway/routes покажет все зарегистрированные маршруты в runtime — удобно для дебага. Добавьте management.endpoint.gateway.enabled=true в конфиг и можно динамически обновлять маршруты через /actuator/gateway/refresh без перезапуска.

══════ Навигация ══════
Вакансии • Задачи • Собесы

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

#Enterprise
  • 👍 11
  • ❤ 2
  • 🔥 2
  • 🎉 1
Post #7477 2.48K
💭 Apache Kafka: как не терять данные под нагрузкой

Классическая проблема растущего проекта: сервис уведомлений начинает захлёбываться. В пике прилетает 10к запросов в секунду, а он обрабатывает 3к. Остальные просто теряются.

Можно горизонтально масштабировать, но это не решает проблему архитектурно. А Kafka решает.

Идея простая: Producer пишет, Consumer читает в своём темпе. Никто никого не ждёт. Никто никого не роняет.

1️⃣ Producer: отправляем событие

@Service
@RequiredArgsConstructor
public class OrderService {

private final KafkaTemplate<String, OrderEvent> kafkaTemplate;

public void createOrder(Order order) {
orderRepository.save(order);

OrderEvent event = new OrderEvent(order.getId(), order.getUserId());
kafkaTemplate.send("order-created", order.getUserId().toString(), event);
// топик ключ партиции payload
}
}


Ключ партиции — важная деталь. Kafka гарантирует порядок сообщений внутри одной партиции. Если передаёшь userId как ключ — все события одного пользователя попадут в одну партицию и будут обработаны строго по порядку.

2️⃣ Consumer: читаем и обрабатываем

@Component
public class NotificationConsumer {

@KafkaListener(
topics = "order-created",
groupId = "notification-group",
concurrency = "3" // 3 потока = читаем 3 партиции параллельно
)
public void handle(OrderEvent event) {
notificationService.send(event.getUserId());
}
}


groupId определяет логическую группу потребителей. Kafka гарантирует: одно сообщение получит ровно один инстанс внутри группы. Хочешь, чтобы событие получили оба сервиса уведомлений и аналитики? Разные groupId и каждый читает топик независимо.

3️⃣ Партиции и масштабирование

order-created (3 партиции)
├── partition-0 → consumer-instance-1
├── partition-1 → consumer-instance-2
└── partition-2 → consumer-instance-3


Не хватает скорости обработки → поднимаешь ещё инстансов. Kafka сама перераспределит партиции. Но инстансов больше, чем партиций держать смысла нет, лишние будут просто простаивать.

4️⃣ Что делать, если Consumer упал

Kafka хранит сообщения на диске (по умолчанию 7 дней). Consumer сам трекает, до какого offset он дочитал.

spring:
kafka:
consumer:
auto-offset-reset: earliest # читать с начала, если offset не найден
enable-auto-commit: false # коммитим offset вручную — только после успешной обработки


enable-auto-commit: false — критически важная настройка. Если Consumer упал в середине обработки, он перечитает сообщения с последнего закоммиченного offset. При true — offset уже сдвинулся, сообщение потеряно.

5️⃣ Dead Letter Topic: что делать с ядовитыми сообщениями

Иногда одно сообщение падает раз за разом: битые данные, баг в логике. Consumer уходит в бесконечный retry и встаёт колом.

@Bean
public DefaultErrorHandler errorHandler(KafkaTemplate<String, Object> kafkaTemplate) {
var recoverer = new DeadLetterPublishingRecoverer(kafkaTemplate);
var backoff = new FixedBackOff(1000L, 3); // 3 попытки с паузой 1с
return new DefaultErrorHandler(recoverer, backoff);
}


После 3 неудачных попыток сообщение уедет в топик order-created.DLT. Основной поток не заблокирован, разбираешься с проблемой отдельно.

📌 Когда Kafka, а когда нет

Нужен ответ прямо сейчас → REST
Получатель может быть недоступен → Kafka
Один источник и много потребителей → Kafka
Аудит и история событий → Kafka
Простой CRUD без нагрузки → REST

Kafka не серебряная пуля. Она добавляет операционную сложность: нужно думать об idempotency, порядке сообщений, мониторинге lag у Consumer-групп. Но когда система начинает терять данные под нагрузкой, цена этой сложности оправдана.

══════ Навигация ══════
Вакансии • Задачи • Собесы

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

#CoreJava
  • 🔥 7
  • 👍 5
  • ❤ 3
Post #7476 2.56K
👑 Магия IntelliJ IDEA

Если используешь Ctrl + P (подсказка параметров метода), то вот ещё один полезный хот кей: Shift + Ctrl + I → быстрый просмотр определения.

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

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

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


— Наведи курсор на метод, поле или класс, нажми Ctrl + Shift + I — появится всплывающее окно с реализацией.
— Работает и в дебаге, и при просмотре внешних библиотек (если есть исходники).

══════ Навигация ══════
Вакансии • Задачи • Собесы

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

#CoreJava
  • 👍 11
  • 🔥 6
  • ❤ 3
Post #7475 2.41K
🌸 Поздравляем с 8 марта

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

Пусть сегодня всё задуманное сбывается, улыбок будет больше, чем поводов для них, а день подарит только приятные сюрпризы!

С праздником, коллеги 💐

🐸 Библиотека джависта
  • ❤ 15
  • 👍 3
  • 🔥 3
  • 👾 1
Post #7474 2.31K
💥 Открытый вебинар | ИИ-агенты в продакшене: от хайпа к деньгам

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

Полина Полунина, руководитель AI-направления Альфа-Банка, расскажет честно:

▪️ Чем агент отличается от «просто GPT с промптом» и когда бизнесу достаточно обычного LLM
▪️ 3 реальных кейса из корпоративной среды: что взлетело, а что нет
▪️ Live-демо работающего агента
▪️ ТОП-5 граблей, на которые наступают команды при внедрении

⏱️ 10 марта в 19:00 (МСК)

🎁 Участники получат промокод на скидку на самый полный курс по ИИ-агентам

👉 Регистрируйся
Post #7473 2.37K
🔍 Чтение csv файла

Простая команда на случай, когда надо быстро и в удобном формате прочитать CSV-файл в терминале:
$ cat inventory.csv | column -t -s,


Флаг -s указывает на использование запятых в качестве разделителей, а -t форматирует выходные данные в чистую таблицу.

══════ Навигация ══════
Вакансии • Задачи • Собесы

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

#CoreJava
  • 👍 7
  • ❤ 4
  • 🔥 3
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →