Gradle 9.5.1 в одноразовом CI: сокращаем запуск сборки
В свежем CI-контейнере нет состояния предыдущего запуска, поэтому Gradle снова получает дистрибутив и готовит служебные файлы. Для Java-проекта это лишнее время до выполнения задач сборки.
В разборе запуска Gradle проверяют три приёма: использовать дистрибутив
Результаты служат ориентиром: небольшой Spring Boot-проект собирали в чистом Docker-окружении по пять раз, базовый прогон занял 31,7 секунды. Повторите замеры на своей кодовой базе: в крупной сборке больше времени могут отнимать зависимости, конфигурация или выполнение задач.
В свежем CI-контейнере нет состояния предыдущего запуска, поэтому Gradle снова получает дистрибутив и готовит служебные файлы. Для Java-проекта это лишнее время до выполнения задач сборки.
В разборе запуска Gradle проверяют три приёма: использовать дистрибутив
-bin вместо -all, восстанавливать каталоги Wrapper и заранее готовить generated-gradle-jars вместе с jars-9. Версии образа и Wrapper нужно согласовать, а после обновления Gradle пересобрать подготовленный образ и проверить пути кэша.Результаты служат ориентиром: небольшой Spring Boot-проект собирали в чистом Docker-окружении по пять раз, базовый прогон занял 31,7 секунды. Повторите замеры на своей кодовой базе: в крупной сборке больше времени могут отнимать зависимости, конфигурация или выполнение задач.
Как проверить отправку Kafka-сообщения в Spring Boot без Docker
В интеграционном тесте с Embedded Kafka настоящий брокер запускается внутри тестового процесса. Аннотация
Тест подтверждает доставку от продюсера до брокера и обратно к потребителю, но не результат работы метода с
В интеграционном тесте с Embedded Kafka настоящий брокер запускается внутри тестового процесса. Аннотация
@EmbeddedKafka создаёт топик greetings, поэтому внешняя Kafka и Docker не нужны.KafkaTemplate публикует сообщение, а отдельный KafkaConsumer получает запись через KafkaTestUtils.getSingleRecord. Перед отправкой тест считывает сообщения, созданные ApplicationRunner при запуске, чтобы проверка не забрала старую запись.Тест подтверждает доставку от продюсера до брокера и обратно к потребителю, но не результат работы метода с
@KafkaListener. Эффект обработчика стоит проверять отдельно: так транспортная интеграция и бизнес-логика не маскируют ошибки друг друга.Java 25 и Micronaut: упрощаем точку входа через compact source file
В Java 25 механизм compact source files финализирован в JEP 512. Он позволяет запускать программу без явного объявления класса и метода
Меняется и Gradle: вместо полного имени
Для существующего проекта это локальное упрощение стартового кода, но структуру исходников придётся проверить: файл без объявления пакета лучше держать в корне
В Java 25 механизм compact source files финализирован в JEP 512. Он позволяет запускать программу без явного объявления класса и метода
public static void main. Для Micronaut точка входа сокращается до импорта, void main() и вызова Micronaut.run().Меняется и Gradle: вместо полного имени
com.example.Application в mainClass достаточно Application. Неявный класс получает имя файла, поэтому Application.java и значение mainClass должны совпадать точно.Для существующего проекта это локальное упрощение стартового кода, но структуру исходников придётся проверить: файл без объявления пакета лучше держать в корне
src/main/java, иначе IDE и инкрементальная компиляция могут работать хуже. В примере с конфигурацией Gradle показаны оба варианта точки входа.Spring Boot 4: как выбрать режим RestTestClient для проверки REST API
Новый RestTestClient позволяет сохранить один способ вызова API и менять охват теста. Клиент привязывается к контроллеру для модульного теста, к MockMvc для проверки валидации и Spring Security, к WebApplicationContext для интеграционного теста либо к запущенному серверу для сквозной проверки по HTTP.
При привязке к контроллеру Spring-контекст не поднимается: зависимости нужно создать или подменить самостоятельно, а валидация бинов и безопасность не проверяются. В примере
Разбор четырёх режимов RestTestClient показывает настройку клиента и проверки ответа API. Для подключения нужен тестовый модуль
Новый RestTestClient позволяет сохранить один способ вызова API и менять охват теста. Клиент привязывается к контроллеру для модульного теста, к MockMvc для проверки валидации и Spring Security, к WebApplicationContext для интеграционного теста либо к запущенному серверу для сквозной проверки по HTTP.
При привязке к контроллеру Spring-контекст не поднимается: зависимости нужно создать или подменить самостоятельно, а валидация бинов и безопасность не проверяются. В примере
@AuthenticationPrincipal получает объект с полями null, если не зарегистрировать собственный обработчик аргумента. Это ограничение данного режима и конфигурации теста.Разбор четырёх режимов RestTestClient показывает настройку клиента и проверки ответа API. Для подключения нужен тестовый модуль
spring-boot-starter-webmvc-test.Как убрать временные MemorySegment при доступе к нативной памяти в Java
В горячем цикле обёртка MemorySegment для каждого нативного адреса создаёт короткоживущие объекты и нагружает GC. Разбор арифметики указателей через FFM API показывает другой путь: один глобальный сегмент начинается с адреса 0 и расширяется через
VarHandle, построенный из описания структуры, получает этот сегмент как базу, а числовой адрес как смещение. Новая обёртка на каждом проходе не нужна. В авторском JMH-тесте такой вариант дал примерно 21 млн против 1,49 млн операций в миллисекунду.
Цена ускорения: глобальный сегмент не проверит, существует ли память по адресу и не была ли она освобождена. Для горячего участка сначала измерьте аллокации и производительность собственным JMH-тестом, а время жизни памяти контролируйте отдельно.
В горячем цикле обёртка MemorySegment для каждого нативного адреса создаёт короткоживущие объекты и нагружает GC. Разбор арифметики указателей через FFM API показывает другой путь: один глобальный сегмент начинается с адреса 0 и расширяется через
reinterpret до Long.MAX_VALUE.VarHandle, построенный из описания структуры, получает этот сегмент как базу, а числовой адрес как смещение. Новая обёртка на каждом проходе не нужна. В авторском JMH-тесте такой вариант дал примерно 21 млн против 1,49 млн операций в миллисекунду.
Цена ускорения: глобальный сегмент не проверит, существует ли память по адресу и не была ли она освобождена. Для горячего участка сначала измерьте аллокации и производительность собственным JMH-тестом, а время жизни памяти контролируйте отдельно.
👍1👏1
Spring Boot 3.5 и 4: подключаем Fory JSON к MVC и WebFlux
Spring Fory 1.1.0 требует Java 17 или новее. Для Boot 4 предназначен
При миграции настройки придётся перенести явно: аннотации Jackson и параметры
Руководство по интеграции показывает API заказов, настройку преобразования JSON и вариант без Spring Boot. Бенчмарки сериализации не гарантируют такой же прирост HTTP-производительности: результат нужно измерять на своём приложении.
Spring Fory 1.1.0 требует Java 17 или новее. Для Boot 4 предназначен
fory-json-spring-boot-starter, для Boot 3.5 — fory-json-spring-boot3-starter. Стартер выбирает интеграцию для MVC или WebFlux, а контроллеры сохраняют привычные @RequestBody, Mono и Flux.При миграции настройки придётся перенести явно: аннотации Jackson и параметры
spring.jackson.* не управляют Fory. Стоит отдельно проверить имена полей и весь JSON-контракт. Ограничение входных данных в MVC относится ко всему телу запроса, а при потоковом NDJSON в WebFlux — к каждому значению в Flux.Руководство по интеграции показывает API заказов, настройку преобразования JSON и вариант без Spring Boot. Бенчмарки сериализации не гарантируют такой же прирост HTTP-производительности: результат нужно измерять на своём приложении.
✍1
JDK 25: как передавать контекст запроса через ScopedValue
В JDK 25 ScopedValue стал постоянным API для идентификаторов запросов, данных пользователя и трассировки. Значение привязывается через
Во вложенной области значение можно временно перепривязать. После её завершения внешняя привязка восстановится, поэтому время жизни контекста видно прямо в коде.
Практический пример с RequestContext показывает проверку через
В JDK 25 ScopedValue стал постоянным API для идентификаторов запросов, данных пользователя и трассировки. Значение привязывается через
where(...).run(...), читается через get() во всей цепочке вызовов и автоматически исчезает после выхода из блока. Это убирает сквозные параметры и ручной ThreadLocal.remove().Во вложенной области значение можно временно перепривязать. После её завершения внешняя привязка восстановится, поэтому время жизни контекста видно прямо в коде.
Практический пример с RequestContext показывает проверку через
isBound() до и после блока. Для миграции ScopedValue подходит читаемому контексту с ограниченным временем жизни. ThreadLocal остаётся для изменяемого состояния потока, прежних версий Java и совместимости с существующими API.JDK 26: когда автовекторизации JIT мало и нужен Vector API
JIT превращает циклы Java в SIMD-инструкции, обрабатывающие несколько чисел за раз. На JDK 26.0.2.1 и Apple M4 Max суммирование миллиона элементов ускорилось примерно вдвое. Вклад оптимизации можно проверить JMH-прогоном с
Vector API с одним аккумулятором дал те же 113 мкс на операцию, а четыре независимых сократили время до 35 мкс: процессору не пришлось ждать предыдущее сложение.
Сравнение JMH-бенчмарков показывает цену ускорения: Vector API остаётся инкубационным, код усложняется, а выигрыш зависит от CPU. Бенчмарк стоит прогнать на production-сервере.
JIT превращает циклы Java в SIMD-инструкции, обрабатывающие несколько чисел за раз. На JDK 26.0.2.1 и Apple M4 Max суммирование миллиона элементов ускорилось примерно вдвое. Вклад оптимизации можно проверить JMH-прогоном с
-XX:-UseSuperWord.Vector API с одним аккумулятором дал те же 113 мкс на операцию, а четыре независимых сократили время до 35 мкс: процессору не пришлось ждать предыдущее сложение.
Сравнение JMH-бенчмарков показывает цену ускорения: Vector API остаётся инкубационным, код усложняется, а выигрыш зависит от CPU. Бенчмарк стоит прогнать на production-сервере.
Как защитить REST API в Spring Boot от несовместимых изменений
В Spring Boot обновление Jackson, смена конфигурации или новая функция могут незаметно нарушить договорённости с клиентами REST API. Контрактные тесты фиксируют ожидаемые запросы и ответы, чтобы поймать расхождение до развёртывания.
Для проверки со стороны провайдера OpenAPI-Diff сравнивает текущую спецификацию со снимком. Метод
Spring Cloud Contract хранит контракты в YAML, а Maven-плагин генерирует проверочные тесты и WireMock-заглушки для клиентов. Если команда контролирует потребителей API, можно передать им ведение контракта через Pact. Практический разбор трёх подходов помогает выбрать схему и настроить проверки совместимости.
В Spring Boot обновление Jackson, смена конфигурации или новая функция могут незаметно нарушить договорённости с клиентами REST API. Контрактные тесты фиксируют ожидаемые запросы и ответы, чтобы поймать расхождение до развёртывания.
Для проверки со стороны провайдера OpenAPI-Diff сравнивает текущую спецификацию со снимком. Метод
isCompatible(), в отличие от строгого isUnchanged(), не отклоняет совместимое добавление новых эндпоинтов.Spring Cloud Contract хранит контракты в YAML, а Maven-плагин генерирует проверочные тесты и WireMock-заглушки для клиентов. Если команда контролирует потребителей API, можно передать им ведение контракта через Pact. Практический разбор трёх подходов помогает выбрать схему и настроить проверки совместимости.
👍1😁1👌1
DAGP 3.5.0 проверяет бинарную совместимость дубликатов классов в Gradle
Если два JAR содержат класс с одинаковым полным именем, JVM загрузит первый найденный в пути классов. Поэтому порядок зависимостей может решить, какая реализация попадёт в работу. На этом же поведении строятся атаки Maven-Hijack.
Dependency Analysis Gradle Plugin запускает проверку через
Разбор проверки Gradle-сборки предлагает предупреждать о дубликатах либо останавливать сборку. Ограничение остаётся: вредоносная реализация с прежними сигнатурами пройдёт такую проверку, поэтому DAGP служит ранним сигналом, а не полной защитой.
Если два JAR содержат класс с одинаковым полным именем, JVM загрузит первый найденный в пути классов. Поэтому порядок зависимостей может решить, какая реализация попадёт в работу. На этом же поведении строятся атаки Maven-Hijack.
Dependency Analysis Gradle Plugin запускает проверку через
buildHealth. При обнаружении дубликатов DAGP 3.5.0 сравнивает поля и методы классов, включая типы, параметры и модификаторы. Несовместимые сигнатуры помогают найти конфликт версий, ошибочную перепаковку библиотеки или подозрительную подмену класса.Разбор проверки Gradle-сборки предлагает предупреждать о дубликатах либо останавливать сборку. Ограничение остаётся: вредоносная реализация с прежними сигнатурами пройдёт такую проверку, поэтому DAGP служит ранним сигналом, а не полной защитой.
Spring Boot 4: настраиваем экспорт логов, метрик и трассировок через OpenTelemetry
В Spring Boot 4 появился собственный OpenTelemetry starter. Spring рекомендует его вместо Java-агента и стороннего starter с альфа-зависимостями.
Для логов нужны Logback appender,
Метрики потребуют Micrometer и дополнительных bean-компонентов, для трассировок достаточно адреса экспорта. Полная схема настройки включает Docker Compose с Grafana LGTM. Проверьте адрес логов: нужен
В Spring Boot 4 появился собственный OpenTelemetry starter. Spring рекомендует его вместо Java-агента и стороннего starter с альфа-зависимостями.
Для логов нужны Logback appender,
logback-spring.xml и вызов install(). В 4.0.0 экспорт без Actuator не работал, обе ошибки исправили в 4.0.1.Метрики потребуют Micrometer и дополнительных bean-компонентов, для трассировок достаточно адреса экспорта. Полная схема настройки включает Docker Compose с Grafana LGTM. Проверьте адрес логов: нужен
/v1/logs, не /v1/traces.