Чашечка Java
8.4K subscribers
3.9K photos
13 videos
56 files
6.36K links
Лучшие материалы по Java на русском и английском

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels
Download Telegram
Синтаксис, который восемь лет лежит в драфте JEP, предлагают включать препроцессором перед javac

Декоратор или адаптер наполовину состоит из методов, которые только зовут то же самое у обёрнутого объекта. В самой JDK у Collections.UnmodifiableCollection таких методов 14.

JEP 8209434 «Concise Method Bodies» Брайана Гётца предлагает записывать их как лямбды: public int size() -> c.size(); или ссылкой на метод: public int size() = aList::size;. Заявку подали в августе 2018 года, и она до сих пор в статусе Draft: ни целевого релиза, ни preview-флага. В C# такие тела работают с 2015 года.

Автор статьи ждать перестал и собрал препроцессор java-composition: он разворачивает такие тела в обычный Java-код до того, как файл дойдёт до javac, начиная с Java 8.

Цена — исходник, который без препроцессора не соберётся ни у кого. Взяли бы такое в проект, который поддерживать ещё пять лет?
🤣1
Девять convention-плагинов Gradle в проде JetBrains заменили декларативным конфигом сборки

Логика сборки крупного JVM-проекта обычно живёт в buildSrc: convention-плагины на Kotlin, которые сами надо компилировать и чинить при каждом апгрейде Gradle. JetBrains перевела на Kotlin Toolchain бэкенд klibs.io: прод на JDK 21, Spring Boot 4 со Spring AI, PostgreSQL и OpenSearch. Девять плагинов свернулись в шаблоны Toolchain, а Jib и Git Properties, у которых встроенного аналога нет, переписали как локальные плагины.

Отдельно про Maven Central: Sonatype скоро включит квоты на число файлов в публикации. В 0.12 из неё убрали контрольные суммы файлов подписи (.asc.sha1) — они не нужны, а место в квоте занимают.

Toolchain пока в версии 0.x, публикация библиотек в статусе preview, для фич 0.12 нужна IntelliJ IDEA 2026.2.1. Переносить рабочую сборку рано, а в список на перепроверку положить стоит.
Промпт прошёл все офлайн-проверки и всё равно уронил P95 на 38%, но канареечный выкат ловит это за минуты

Правку промпта не отсекает ни один привычный гейт: компилятор её не видит, юнит-тесты зелёные, офлайн-набор из 40 кейсов тоже. А на живом трафике переформулированное описание инструмента научило агента вызывать его дважды за ход: вызовов на диалог стало 5,4 вместо 3,1, P95 вырос на 38%. Тестовые транскрипты короткие по замыслу, реальные диалоги длинные, и каждый лишний вызов удваивает ожидание.

В десятой части серии про агента на Spring Boot собрана рантайм-обвязка: раздача процента трафика на новую версию, автоматический переход на запасную модель при деградации основной и потолок расходов на модель.

Если промпты у вас едут в прод вместе с кодом, начинать стоит с процента трафика, который возвращается в ноль одной настройкой, и графика вызовов инструментов на диалог.
👎1
Общий обработчик исключений убирает try/catch из контроллеров, но свалка переезжает в него самого

В контроллере на каждый эндпоинт по два catch: свой UserAlreadyExistsException в 409, остальное в 500 со строкой «Internal server error». В соседнем контроллере то же самое, но статус и текст уже другие. Всё это уносится в @RestControllerAdvice, и метод снова возвращает только успешный ответ.

Спор начинается дальше. В статье на dev.to автор разводит бизнес-ошибки и системные. Вторые обычно закрывают одним обработчиком на Exception.class, и он же превращает в аккуратный 500 то, что должно было упасть громко и попасть в алерты.

А со Spring Boot 3 в фреймворке уже есть ProblemDetail: стандартное тело ошибки по RFC. Свой ErrorResponse при этом всё равно пишут почти все.

Как разложены исключения у вас?
Совет не оптимизировать руками и довериться JIT держался на цене специалиста, а она рухнула

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

Дэн Лу в эссе «There's no reason for software to be slow anymore» пишет, что человеко-время на такую итерацию упало в тысячи раз: запуск агента на его собственном сценарии с ripgrep занял около двух минут. Джейми Брэндон отдал агенту недоделанное тестовое Anthropic по производительности и получил результат лучше своего.

Java стоит на обратном: пиши предсказуемый код, JIT разберётся. Это верно, пока проверка гипотезы дороже выигрыша. Теперь она стоит минуты, зато поддерживать неочевидные правки в горячем пути всё равно людям. Рабочий процесс для Spring Boot. Пустили бы агента в горячий путь своего сервиса?
😁1
На JVM серверный HTML до сих пор собирают шаблонами, хотя соседние экосистемы давно перешли на компоненты

Вёрстка живёт в шаблонах Thymeleaf или FreeMarker: опечатка в имени поля всплывает в рантайме, а рефакторинг в IDE до неё не дотягивается.

JetBrains разбирает в блоге Kotlin, как закрыть этот пробел. Библиотека Compose HTML уже собирает веб-интерфейс на Kotlin поверх Compose-рантайма и компилирует его в JS. Если добавить JVM-таргет, те же компоненты отрендерятся в HTML на сервере: автодополнение, рефакторинг и проверки компилятора вместо строковых шаблонов.

В посте: почему нынешняя отрисовка Compose для веба в canvas ломает SEO, скорость загрузки и доступность.

Это исследование, а не анонс релиза: обязательств JetBrains не берёт. В план миграции не ставить, а вот в список на перепроверку положить стоит.
«Невозможная» порча базы может прятаться ниже вашего приложения

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

Условия выглядели безопасно: к базе каждого шарда обращался один Go-процесс, полные снимки каждые несколько минут уходили в S3. Причина всё же оказалась в SQLite: ошибка жила там не менее 16 лет.

Для Java-команд этот кейс полезен как методика расследования сбоев, которые документация считает невозможными. В разборе на DEV Community остались ход поиска и чек-лист для Spring Boot с Postgres, MySQL или SQLite.
Пакетные задачи Spring AI с DeepSeek выгоднее запускать по расписанию

Пакетная генерация через DeepSeek V4 теперь зависит от времени запуска. С 16 августа часы пик идут с 01:00 до 04:00 и с 06:00 до 10:00 UTC. В остальные 17 часов тариф вдвое ниже пикового.

Эта скидка действует только относительно нового пика. Для V4 Pro вне пика миллион входных токенов подорожал с $0,435 до $0,66, выходных: с $0,87 до $1,98. Попадание в кеш стало дороже в шесть раз даже по внепиковому тарифу.

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

У PostConstruct, InitializingBean и процессоров разные места в цикле. Поэтому точку расширения стоит выбирать после того, как определён обрабатываемый объект.

До создания экземпляров BeanFactoryPostProcessor работает с определениями бинов. BeanPostProcessor обрабатывает созданный экземпляр до и после инициализации. Для инициализации есть @PostConstruct и InitializingBean, для очистки: @PreDestroy и DisposableBean. SmartLifecycle координирует запуск и остановку компонентов с активным состоянием.

В материале на DEV Community эти точки собраны в примерах с тестами и документацией. При ревью сначала определите этап контейнера, затем выбирайте точку расширения.
Solon Cloud позволяет менять сервисную инфраструктуру без переписывания бизнес-кода

Планируете менять реестр сервисов, центр конфигурации или шину событий без каскада правок в бизнес-логике? Solon Cloud ставит между кодом и инфраструктурой общий слой: приложение вызывает CloudConfigService, CloudDiscoveryService или CloudEventService, а запрос выполняет выбранный плагин.

Всего набор определяет 13 сервисных интерфейсов. Для перехода с локальной реализации на Nacos или Consul меняются зависимость и YAML-конфигурация, а бизнес-код остаётся прежним.

В разборе Solon Cloud на DEV Community есть схема слоя и полный перечень интерфейсов, включая хранение файлов, задания, распределённые блокировки и генерацию идентификаторов. Для крупной кодовой базы это способ заранее оставить путь к смене инфраструктуры.
Устаревшие API можно удалять без лотереи в большой Java-кодбазе

Метод годами помечен @Deprecated, но удаление может сломать неизвестного потребителя. ArchUnit рассчитан на JUnit-проверку одного репозитория, чего мало для общих библиотек.

Nebula ArchRules поставляет правила вместе с библиотекой отдельным JAR. Gradle-плагин запускает их там, где библиотека подключена как зависимость. Анализ байткода делает одно правило общим для Java, Kotlin и Scala.

В CI-сборке авторы видят проекты, которые используют устаревшие, экспериментальные или непубличные API. Netflix TechBlog разбирает решение: 358 правил уже работают более чем в 5000 репозиториев и находят почти миллион нарушений. Так потребителей можно найти до изменения общего API.
1 ноября записи в DynamoDB начнут падать там, где сегодня проходят, но это проверяется заранее

Вызов, попавший в троттлинг, SDK сейчас молча повторяет до девяти раз, и запись доходит. С 1 ноября 2026 AWS меняет дефолты ретраев: у DynamoDB останется четыре попытки вместо девяти, у прочих сервисов три вместо четырёх, пауза при троттлинге вырастет с 500 мс до 1000 мс.

По логам не понять, кого это заденет: наружу выходит успех или финальная ошибка, а попытки между ними SDK не показывает. В AWS SDK for Java 2.44+ новые значения включает переменная AWS_NEW_RETRIES_2026=true, но это рубильник: цена выясняется в бою.

Ответ даёт библиотека retrylens: ExecutionInterceptor пишет каждую попытку в кольцевой буфер, а симулятор считает по этим записям, чем бы тот же трафик кончился на новых дефолтах. Запросы он не переотправляет и ключи доступа не просит, так что снять картину можно на проде.
1
Версию зависимости агент называет по памяти, но klibs.io отдаёт её из живого индекса через MCP

Просите ассистента добавить библиотеку, а он вписывает в pom.xml версию, которой в Maven Central нет или которая отстала на год. Сборка падает, либо вы тянете артефакт с уже закрытой уязвимостью: версия взята из обучающих данных, а не из репозитория.

JetBrains показала обходной путь: у каталога klibs.io (4200+ проектов, данные из GitHub и Maven Central) появился MCP-сервер. Агент ходит в него запросом по платформе и цели, среди которых есть JVM, и получает последнюю опубликованную версию пакета из индекса.

Каталог собран вокруг Kotlin Multiplatform, так что enterprise-стек закрывает частично. Интереснее приём: справочник по зависимостям как инструмент рядом с агентом. Если ваши ассистенты уже правят pom.xml, проверьте, откуда они берут версии, и до тех пор держите ревью зависимостей ручным.
3👍3😁2🤔2🔥1👏1
Все дела подождут, потому что сегодня ваш день!

Поздравляем с Днем программиста и желаем меньше багов и больше фич, меньше созвонов и больше фокуса, меньше тасок с пометкой «срочно» и больше времени на отдых.

Забирайте подарок из нашей IT-коробки. Мы уверены, этот презент точно пригодится вам в работе: https://tprg.ru/NxFt
Что важнее ИИ-агенту: скорость Go или проверки Java

Когда агент генерирует сотни строк за секунды, узким местом становится проверка кода. Go предлагает быстрый компилятор, единый форматтер gofmt и развитую стандартную библиотеку. Java отвечает record-типами и sealed-интерфейсами: конструктор record требует все компоненты, а switch по закрытой иерархии должен обработать каждый вариант.

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

Автор разбора спора Google и Java-разработчиков предлагает оценивать весь контур: компилятор, тесты, форматирование и ревью. Где у вас проходит граница между коротким циклом сборки и строгими проверками типов?
👍1
Как извлекать поля из XML в Java без дерева объектов

DOM и JAXB создают объекты для всего документа, даже если нужно несколько значений. Fletch для Java 17+ идёт по исходным байтам и создаёт только запрошенные строки, числа и записи: без дерева, рефлексии и промежуточных событий. Сопоставление путей читает UTF-8-поток через скользящее окно 64 КБ, поэтому обрабатывает набор документов больше доступной памяти.

В JMH на Temurin/JDK 25 Fletch показал 283,7 операции/мс против 96,4 у ручного цикла Woodstox на XML с одной позицией. Это бенчмарк проекта, поэтому перед миграцией его стоит повторить на своих документах.

Fletch подходит для массового чтения полей, но не поддерживает запись XML, XPath, XSLT и валидацию схем. Код, два API и команды запуска тестов есть в материале DEV Community.
Как получить Post и User без загрузки PostDetails в Hibernate

Если PostDetails опциональна, запрос от неё с JOIN FETCH не подходит: запись может отсутствовать, а бизнес-логике нужны только Post и связанный User.

Решение из разбора Vlad Mihalcea: начать JPQL-запрос с Post, присоединить PostDetails по общему идентификатору, затем User и вернуть обе сущности через конструктор Java Record. Если промежуточной записи нет, поле пользователя будет null.

Hibernate добавляет выбранные сущности в текущий контекст персистентности. Изменение Post поэтому превращается в UPDATE при flush(). Такой приём позволяет не добавлять обратную связь @OneToOne или @OneToMany в родительскую сущность только ради чтения.
👍1
Как Project Leyden помогает искать задержки запуска Quarkus

Quarkus с Project Leyden переносит загрузку и связывание классов в тренировочный запуск, а затем сохраняет их подготовленное состояние. В статье REST-приложение из quarkus create app стартует за 130 мс. При старте около 100 мс расход даже в 5 мс уже заметен.

Когда загрузка классов почти исчезла из профиля, проявились другие затраты: рефлексия для проверки возможностей JDK, разбор аннотаций с созданием прокси-объектов и поиск отсутствующих классов или ресурсов. Такой поиск может открыть множество JAR-файлов лишь для ответа «не найдено».

Для enterprise-библиотек вывод практический: проверки совместимости и редко меняющиеся метаданные стоит по возможности обрабатывать при сборке, а не при каждом старте приложения. В разборе в блоге Quarkus это показано на профилях Netty и Hibernate ORM.
2🔥1
В JDK 27 и 28 ускорили операции Curve25519

С JDK 27 build 14 изменения внутренних структур данных повысили пропускную способность операций на Curve25519: на 49–54% для генерации ключей и согласования по X25519, на 46–49% для генерации ключей, подписи и проверки по Ed25519, на 27–51% для постквантового гибридного обмена X25519MLKEM768.

В JDK 28 build 5 добавили встроенные оптимизации с машинными инструкциями для конкретной архитектуры. На x86_64 они дают ещё 12–20% в зависимости от алгоритма, на AArch64: 7–15%. Приложения получают ускорение через JCE, а обмен ключами TLS 1.3 ещё и через JSSE.

Обе версии пока доступны как ранние сборки. Для миграционного плана их можно проверить на своей архитектуре и нагрузке. Диапазоны и ссылки на тесты приведены в материале Inside Java.
Как построить многоуровневую защиту LLM-вызовов в Spring AI 2.0

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

Граница встроенного фильтра: поиск чувствителен к регистру. pass заблокирует вопрос о передаче аргумента, а PASSWORD пройдёт. В примере выходной перехватчик ищет секрет в ответе без учёта регистра и заменяет ответ до возврата клиенту. Входной слой маскирует имя, почту и номер карты до обращения к модели.

Для корпоративной кодовой базы вывод практический: проверяйте запрос и ответ, а SafeGuardAdvisor считайте одним рубежом защиты. В статье Дэна Веги есть код четырёх слоёв и порядок их подключения в Spring AI.
Как собрать движок отказоустойчивых сценариев на Java и SQLite

Persistasaurus показывает устройство движка, который сохраняет состояние многошагового Java-сценария. Метод с @Flow задаёт сценарий, методы с @Step обозначают сохраняемые шаги, а SQLite хранит их параметры, статусы и результаты.

После сбоя сценарий запускают с тем же UUID. Завершённые шаги получают результаты из журнала, а упавший шаг выполняется повторно. Так приложение не дублирует уже успешные операции, например дорогие и недетерминированные обращения к большим языковым моделям.

В разборе Gunnar Morling есть схема журнала и критерий для границ шага: сохранять стоит долгие, дорогие или трудно воспроизводимые операции. Это учебный прототип, а не готовый промышленный движок, но по нему удобно разобрать механику контрольных точек и восстановления Java-сервисов.
1😁1