Всем привет!
Интересная статья про динамическую перезагрузку properties https://www.baeldung.com/spring-reloading-properties в Java приложении.
Два варианта:
1) Apache Сommons Сonfiguration
2) Spring Cloud
Первое работает через отслеживание изменений в файле, второе - управляемое извне перечитывание после вызова /refresh endpoint.
#java #cloud #spring_boot
Интересная статья про динамическую перезагрузку properties https://www.baeldung.com/spring-reloading-properties в Java приложении.
Два варианта:
1) Apache Сommons Сonfiguration
2) Spring Cloud
Первое работает через отслеживание изменений в файле, второе - управляемое извне перечитывание после вызова /refresh endpoint.
#java #cloud #spring_boot
Baeldung
Reloading Properties Files in Spring | Baeldung
Learn a few approaches to getting property values to reload in Spring Beans, including Spring Cloud's refresh scope.
Всем привет!
Наверняка все видели псевдографический баннер в логах при запуске Spring приложений. Так вот его текст можно менять, использовать в тексте переменные среды или даже написать логику его генерации на Java. И наконец его можно просто отключить. Делали: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.spring-application.banner Генератор псевдографики: https://devops.datenkollektiv.de/banner.txt/index.html
Фича наверное малополезная, но забавная)
#spring
Наверняка все видели псевдографический баннер в логах при запуске Spring приложений. Так вот его текст можно менять, использовать в тексте переменные среды или даже написать логику его генерации на Java. И наконец его можно просто отключить. Делали: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.spring-application.banner Генератор псевдографики: https://devops.datenkollektiv.de/banner.txt/index.html
Фича наверное малополезная, но забавная)
#spring
devops.datenkollektiv.de
Spring Boot banner.txt generator
Online Spring Boot Banner Generator (with FIGlet Fonts)
Всем привет!
У любого Spring Boot приложения есть настройки. В базовом варианте они хранятся в application.yaml файле. Но вообще говоря алгоритм, по которым Spring ищет эти настройки достаточно сложный. Вот тут https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config и вот тут https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.files он описан детальнее.
Когда это "тайное знание" может быть полезно - если нужно задать настройки по умолчанию или, наоборот, переопределить их. Или разобраться - откуда тянется та или иная настройка.
#spring_boot #spring
У любого Spring Boot приложения есть настройки. В базовом варианте они хранятся в application.yaml файле. Но вообще говоря алгоритм, по которым Spring ищет эти настройки достаточно сложный. Вот тут https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config и вот тут https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.files он описан детальнее.
Когда это "тайное знание" может быть полезно - если нужно задать настройки по умолчанию или, наоборот, переопределить их. Или разобраться - откуда тянется та или иная настройка.
#spring_boot #spring
Всем привет!
Чем хорош Spring Framework?
1) Inverse of Control и Dependency Injection
2) Очень много модулей-адаптеров к различным технологиям: Data, Data Kafka, Web MVC, WebFlux, Security, Statemachine, Cloud ... с упрощенным и насколько это возможно единообразным API.
Но это не все.
Но Spring приходит на помощь и там, где его не особо ждали) Хочу рассказать о менее известном, но полезном функционале Spring:
1) Расширенный маппинг Enum при передаче значений через REST API: https://www.baeldung.com/spring-boot-enum-mapping
2) Улучшение логирования при падении Spring Boot при старте - все эти bean not found exception: https://www.baeldung.com/spring-boot-failure-analyzer
3) Централизованная обработка ошибок: https://www.baeldung.com/exception-handling-for-rest-with-spring
#spring #spring_boot
Чем хорош Spring Framework?
1) Inverse of Control и Dependency Injection
2) Очень много модулей-адаптеров к различным технологиям: Data, Data Kafka, Web MVC, WebFlux, Security, Statemachine, Cloud ... с упрощенным и насколько это возможно единообразным API.
Но это не все.
Но Spring приходит на помощь и там, где его не особо ждали) Хочу рассказать о менее известном, но полезном функционале Spring:
1) Расширенный маппинг Enum при передаче значений через REST API: https://www.baeldung.com/spring-boot-enum-mapping
2) Улучшение логирования при падении Spring Boot при старте - все эти bean not found exception: https://www.baeldung.com/spring-boot-failure-analyzer
3) Централизованная обработка ошибок: https://www.baeldung.com/exception-handling-for-rest-with-spring
#spring #spring_boot
Baeldung
Enum Mapping in Spring Boot | Baeldung
Explore different ways to implement case-insensitive enum mapping in Spring Boot.
Всем привет!
Хочу продолжить серию постов про #microservices
Я уже писал про их плюсы и минусы. Одним из главных минусов является увеличенная сложность развертывания и поддержки, а также накладные расходы на сетевое взаимодействие. Как ответ на эту сложность может возникнуть идея - а давайте сделаем несколько независимых модулей в одном микросервисе, а потом при необходимости их разделим. Ключевое слово здесь - независимый. Идея на самом деле здравая. "Модулем" здесь может быть модуль Maven\Gradle или даже пакет. Но есть одна проблема: если не следить за связями между "модулями" - они со временем становятся связанными и получается тот самый спагетти код))) А тогда выделение нового микросервиса превратится в распутывание клубка зависимостей. Значит нужна проверка границ "модулей". Лучший способ сделать надежную постоянно выполняемую проверку - это написать unit тест. И запускать его на prcheck и сборке конечно же. Но любой тест должен быть антихрупким - т.е. при изменениях в коде оставаться актуальным. В нашем случае - в случае добавлении\изменении\удалении "модулей" в проекте.
К чему я веду: есть технология, решающая эту проблему - Spring Modulith https://spring.io/projects/spring-modulith
А вот статья, описывающая предпосылки его появления более подробно и способ его использования: https://habr.com/ru/articles/701984/
Мне нравится.
Зависимость от Spring на мой взгляд не является большим минусом. Требование объявить все пакеты в одном модулей Maven\Gradle - минус чуть пожирнее, но на мой взгляд тоже не критично. И сборка в этом случае будет быстрее.
#spring #microservices
Хочу продолжить серию постов про #microservices
Я уже писал про их плюсы и минусы. Одним из главных минусов является увеличенная сложность развертывания и поддержки, а также накладные расходы на сетевое взаимодействие. Как ответ на эту сложность может возникнуть идея - а давайте сделаем несколько независимых модулей в одном микросервисе, а потом при необходимости их разделим. Ключевое слово здесь - независимый. Идея на самом деле здравая. "Модулем" здесь может быть модуль Maven\Gradle или даже пакет. Но есть одна проблема: если не следить за связями между "модулями" - они со временем становятся связанными и получается тот самый спагетти код))) А тогда выделение нового микросервиса превратится в распутывание клубка зависимостей. Значит нужна проверка границ "модулей". Лучший способ сделать надежную постоянно выполняемую проверку - это написать unit тест. И запускать его на prcheck и сборке конечно же. Но любой тест должен быть антихрупким - т.е. при изменениях в коде оставаться актуальным. В нашем случае - в случае добавлении\изменении\удалении "модулей" в проекте.
К чему я веду: есть технология, решающая эту проблему - Spring Modulith https://spring.io/projects/spring-modulith
А вот статья, описывающая предпосылки его появления более подробно и способ его использования: https://habr.com/ru/articles/701984/
Мне нравится.
Зависимость от Spring на мой взгляд не является большим минусом. Требование объявить все пакеты в одном модулей Maven\Gradle - минус чуть пожирнее, но на мой взгляд тоже не критично. И сборка в этом случае будет быстрее.
#spring #microservices
Spring Modulith
Level up your Java code and explore what Spring can do for you.
Всем привет!
Сегодня расскажу про технологию native image.
Стандартная схема работы JVM приложения такая:
1) компилятор превращает исходники в байт-код
2) байт-код запускается на JVM
3) в процессе работы JVM анализирует использование байт-кода и при необходимости оптимизирует его, включая компиляцию в бинарное представление для конкретной процессорной архитектуры. И основные оптимизации надо отметить происходят именно здесь, а не при первичной компиляции. Еще важный момент - классы\библиотеки подгружаются в память не обязательно при старте приложения, а по мере использования. Все это называется JIT - Just in time компиляция. Влиять на нее можно с помощью ряда флагов запуска Java приложения - -server, -client.
Плюс такого подхода - JVM позволяет в 90% случаев игнорировать, на каком железе запускается Java приложение. Минус - долгий старт Java приложения плюс время для "разогрева" и выхода на рабочий режим.
Но с другой стороны с развитием Docker мы и так можем игнорировать особенности железа и ОС на хост-сервере, главное, чтобы там можно было запустить Docker. И наконец кроме долгого старта и разогрева собственно JVM у нас как правило есть Spring с кучей модулей, число которых растет, и в итоге время старта типичного Spring Boot приложения доходит до совсем неприличных величин.
Альтернатива - AOT - Ahead-of-Time compilation. В этом случае мы компилируем исходники в бинарный код в момент первичной компиляции. Причем как собственно приложение, так и JVM и все JAR. Получается такой native image монолит. Проект называется GraalVM https://www.graalvm.org/, официально поддерживается Oracle. Есть open-source версия, основанная на OpenJDK.
Плюс этого подхода - скорость запуска. Это критически важно в облаках, т.к. k8s может "случайно" рестартовать под при изменении конфигурации железа или настроек Deployment. Еще будет выигрыш в скорости обработки запросов, т.к. не тратится CPU и память в runtime на JIT компиляцию.
Какие минусы?
1) невозможна динамическая\ленивая загрузка библиотек\плагинов, classpath фиксируется в момент компиляции. К слову - у этого ограничения есть и плюсы, сложнее эксплуатировать уязвимости типа log4j injection - см. https://t.me/javaKotlinDevOps/4
2) вопрос - откуда компилятор узнает, какой код ему нужно добавить в наш native монолит? Ответ: он идет от метода main. Соответственно, код который явно не вызывается, а, например, вызывается через рефлексию, он не увидит. Соответственно, никакой рефлексии в ПРОМ коде. Что, надо сказать, в целом правильно)
3) аналогично просто так не заработает магия Spring, основанная на рефлексии и динамических прокси. Из чего следует, что мало добавить в Spring приложение AOT компилятор - нужно дорабатывать сам Spring, что и было сделано в Spring Boot 3.2. Другие фреймворки также придется дорабатывать. Например, Mockito до сих пор не работает в native image. Справедливости ради тут причина такая же, как в анекдоте про неуловимого ковбоя Джо - не нужен Mockito в native image)
4) если продолжить про Spring - загрузка бинов по условию: @ConditionalOnProperty, @Profile - тоже не заработает. Нужно указывать при сборке необходимый профиль, чтобы уже при компиляции нужные бины были обнаружены и добавлены в дистрибутив.
5) еще вопрос - но ведь среднее Java приложение + библиотеки + JVM = миллионы строк кода, что будет с компиляцией? Ответ - компиляция будет долгой, до 10 минут на spring boot hello world. Поэтому в документации Spring прямо сказано, что хотя Spring поддерживает запуск тестов в native image - делать так нужно только для интеграционных тестов, лучше на CI, а модульные запускать по старинке, т.к. тут критична скорость получения результата.
#jvm #performance #native_image #spring #docker #buildpacks #cloud #java_start_boost
Сегодня расскажу про технологию native image.
Стандартная схема работы JVM приложения такая:
1) компилятор превращает исходники в байт-код
2) байт-код запускается на JVM
3) в процессе работы JVM анализирует использование байт-кода и при необходимости оптимизирует его, включая компиляцию в бинарное представление для конкретной процессорной архитектуры. И основные оптимизации надо отметить происходят именно здесь, а не при первичной компиляции. Еще важный момент - классы\библиотеки подгружаются в память не обязательно при старте приложения, а по мере использования. Все это называется JIT - Just in time компиляция. Влиять на нее можно с помощью ряда флагов запуска Java приложения - -server, -client.
Плюс такого подхода - JVM позволяет в 90% случаев игнорировать, на каком железе запускается Java приложение. Минус - долгий старт Java приложения плюс время для "разогрева" и выхода на рабочий режим.
Но с другой стороны с развитием Docker мы и так можем игнорировать особенности железа и ОС на хост-сервере, главное, чтобы там можно было запустить Docker. И наконец кроме долгого старта и разогрева собственно JVM у нас как правило есть Spring с кучей модулей, число которых растет, и в итоге время старта типичного Spring Boot приложения доходит до совсем неприличных величин.
Альтернатива - AOT - Ahead-of-Time compilation. В этом случае мы компилируем исходники в бинарный код в момент первичной компиляции. Причем как собственно приложение, так и JVM и все JAR. Получается такой native image монолит. Проект называется GraalVM https://www.graalvm.org/, официально поддерживается Oracle. Есть open-source версия, основанная на OpenJDK.
Плюс этого подхода - скорость запуска. Это критически важно в облаках, т.к. k8s может "случайно" рестартовать под при изменении конфигурации железа или настроек Deployment. Еще будет выигрыш в скорости обработки запросов, т.к. не тратится CPU и память в runtime на JIT компиляцию.
Какие минусы?
1) невозможна динамическая\ленивая загрузка библиотек\плагинов, classpath фиксируется в момент компиляции. К слову - у этого ограничения есть и плюсы, сложнее эксплуатировать уязвимости типа log4j injection - см. https://t.me/javaKotlinDevOps/4
2) вопрос - откуда компилятор узнает, какой код ему нужно добавить в наш native монолит? Ответ: он идет от метода main. Соответственно, код который явно не вызывается, а, например, вызывается через рефлексию, он не увидит. Соответственно, никакой рефлексии в ПРОМ коде. Что, надо сказать, в целом правильно)
3) аналогично просто так не заработает магия Spring, основанная на рефлексии и динамических прокси. Из чего следует, что мало добавить в Spring приложение AOT компилятор - нужно дорабатывать сам Spring, что и было сделано в Spring Boot 3.2. Другие фреймворки также придется дорабатывать. Например, Mockito до сих пор не работает в native image. Справедливости ради тут причина такая же, как в анекдоте про неуловимого ковбоя Джо - не нужен Mockito в native image)
4) если продолжить про Spring - загрузка бинов по условию: @ConditionalOnProperty, @Profile - тоже не заработает. Нужно указывать при сборке необходимый профиль, чтобы уже при компиляции нужные бины были обнаружены и добавлены в дистрибутив.
5) еще вопрос - но ведь среднее Java приложение + библиотеки + JVM = миллионы строк кода, что будет с компиляцией? Ответ - компиляция будет долгой, до 10 минут на spring boot hello world. Поэтому в документации Spring прямо сказано, что хотя Spring поддерживает запуск тестов в native image - делать так нужно только для интеграционных тестов, лучше на CI, а модульные запускать по старинке, т.к. тут критична скорость получения результата.
#jvm #performance #native_image #spring #docker #buildpacks #cloud #java_start_boost
Есть еще ряд интересных моментов. Я расскажу про них на примере Spring Boot native image.
Для борьбы с тем, что часть кода недостижима если идти от точки входа (метод main), есть два инструмента.
1) специальный tracing агент, который можно подключить к приложению, и он будет в runtime логировать такие скрытые вызовы. https://www.graalvm.org/22.3/reference-manual/native-image/metadata/AutomaticMetadataCollection/
2) далее можно создать т.наз. hints - подсказки AOT компилятору, что включить в native image, из того, что он не нашел сам - https://www.graalvm.org/latest/reference-manual/native-image/metadata/ Собственно, большая доля в адаптации фреймворка типа Spring для native image - подготовка таких hints, https://docs.spring.io/spring-boot/docs/3.2.1/reference/html/native-image.html
А что делать если в момент сборки еще не ясно - нужен native image или нет? Или нужны обе версии? Нет проблем - можно совместить оба режима JIT и AOT и создать артефакт, Spring Boot Executable Jar, с байткодом и всеми необходимыми для native image метаданными. И собрать из него native image позже в DevOps pipeline при необходимости.
Для Spring Boot есть два режима сборки. Основной - Native Image Using Buildpacks, в котором в итоге получается docker образ. Для него нужен только Docker на машине-сборщике. И т.наз. Native Build Tools - нужно устанавливать дистрибутив GraalVM, содержащий эти tools, в итоге получается бинарник для железа, на котором происходит сборка.
Итого - штука полезная, но только если вас категорически не устраивает время запуска приложения и все используемые вами фреймворки поддерживают native image.
#jvm #performance #native_image #spring #docker #buildpacks #cloud #startup_time
Для борьбы с тем, что часть кода недостижима если идти от точки входа (метод main), есть два инструмента.
1) специальный tracing агент, который можно подключить к приложению, и он будет в runtime логировать такие скрытые вызовы. https://www.graalvm.org/22.3/reference-manual/native-image/metadata/AutomaticMetadataCollection/
2) далее можно создать т.наз. hints - подсказки AOT компилятору, что включить в native image, из того, что он не нашел сам - https://www.graalvm.org/latest/reference-manual/native-image/metadata/ Собственно, большая доля в адаптации фреймворка типа Spring для native image - подготовка таких hints, https://docs.spring.io/spring-boot/docs/3.2.1/reference/html/native-image.html
А что делать если в момент сборки еще не ясно - нужен native image или нет? Или нужны обе версии? Нет проблем - можно совместить оба режима JIT и AOT и создать артефакт, Spring Boot Executable Jar, с байткодом и всеми необходимыми для native image метаданными. И собрать из него native image позже в DevOps pipeline при необходимости.
Для Spring Boot есть два режима сборки. Основной - Native Image Using Buildpacks, в котором в итоге получается docker образ. Для него нужен только Docker на машине-сборщике. И т.наз. Native Build Tools - нужно устанавливать дистрибутив GraalVM, содержащий эти tools, в итоге получается бинарник для железа, на котором происходит сборка.
Итого - штука полезная, но только если вас категорически не устраивает время запуска приложения и все используемые вами фреймворки поддерживают native image.
#jvm #performance #native_image #spring #docker #buildpacks #cloud #startup_time
www.graalvm.org
GraalVM
GraalVM is an advanced JDK with ahead-of-time Native Image compilation.
Всем привет!
В продолжение темы облачных сервисов - https://telegra.ph/Urovni-pogruzheniya-v-oblako-02-06
#cloud #k8s #openshift #spring
В продолжение темы облачных сервисов - https://telegra.ph/Urovni-pogruzheniya-v-oblako-02-06
#cloud #k8s #openshift #spring
Telegraph
Уровни погружения в облако
В предыдущем посте я говорил про FaaS - Function as a Service. Это максимальная степень передачи инфраструктуры разработки в облако - все кроме кода. Больше - это только пользоваться готовым сервисом - Software as a Service. Захотелось посмотреть - а что…
Всем привет!
Нашел хорошую статью о том, как совместить тестирование Spring контроллеров и один из самых известных фреймворков для тестирования REST - Rest Assured. https://www.baeldung.com/spring-mock-mvc-rest-assured
Кстати, в начале статьи есть ссылка на пример использования чистого Spring MVC Test, если кто его не использовал - можете сравнить синтаксис.
Еще статья хороша тем, что четко разделяет модульные и интеграционные тесты. И я бы разделил точно также) Я иногда задаю вопрос о видах тестов на интервью, ответ мне не всегда нравится. Для ленивых, вкратце - интеграционным тест можно считать, если появляется сеть - открывается порт, вызывается другой процесс, внешнее хранилище, пусть даже и в embedded варианте. Хотя справедливости ради - вопрос холиварный, из-за того, что много пограничных случаев.
#unittests #spring #rest #integration_tests #interview_question
Нашел хорошую статью о том, как совместить тестирование Spring контроллеров и один из самых известных фреймворков для тестирования REST - Rest Assured. https://www.baeldung.com/spring-mock-mvc-rest-assured
Кстати, в начале статьи есть ссылка на пример использования чистого Spring MVC Test, если кто его не использовал - можете сравнить синтаксис.
Еще статья хороша тем, что четко разделяет модульные и интеграционные тесты. И я бы разделил точно также) Я иногда задаю вопрос о видах тестов на интервью, ответ мне не всегда нравится. Для ленивых, вкратце - интеграционным тест можно считать, если появляется сеть - открывается порт, вызывается другой процесс, внешнее хранилище, пусть даже и в embedded варианте. Хотя справедливости ради - вопрос холиварный, из-за того, что много пограничных случаев.
#unittests #spring #rest #integration_tests #interview_question
Baeldung
REST-assured Support for Spring MockMvc | Baeldung
Learn how to test Spring REST controllers using the RestAssuredMockMvc API from REST-assured.
Всем привет!
Продолжим серию с тэгом #interview_question
Вот код:
@Service
public class MyService {
public void syncMethod() {
System.out.println("Synchronous method executed.");
asyncMethod();
}
@Async
public void asyncMethod() {
System.out.println("Async method executed.");
}
}
Что с ним не так?
Подсказка: @Async выполняет код в отдельном потоке.
Еще подсказка: магия Spring работает через proxy объекты. Из-за proxy объектов, к слову, магия ломается на финальных классах, в частности в Kotlin, без специальных настроек.
И последняя подсказка: вызов метода того же класса в Java работает через неявное указание this, и этот вызов идет через пул констант класса
https://ru.stackoverflow.com/questions/846457/Пул-констант-в-java
В общем код проблема в том, что asyncMethod будет вызван синхронно, как обычный метод того же класса, proxy код будет проигнорирован. Аналогичная проблема будет и с @Transactional. Проблема называется self execution.
Решений два:
1) простое и поэтому правильное - вызывать метод asyncMethod() из другого класса
2) сделать self injection - внедрить класс сам в себя. Выглядит странно, может сбить с толку, но наверняка может пригодится в отдельных случаях.
P.S. Еще один оффтопик. Код для поста я попросил сгененировать GigaChat и ChatGPT. Первый не справился, второй - справился, но с третьей попытки. И к тому же его пришлось почистить. Указание на название проблемы - self execution - не помогло, у обоих моделей без уточняющих подсказок выдается пример с рекурсивным вызовом асинхронного метода. В общем быстрее написать самому)
#interview_question #spring #java
Продолжим серию с тэгом #interview_question
Вот код:
@Service
public class MyService {
public void syncMethod() {
System.out.println("Synchronous method executed.");
asyncMethod();
}
@Async
public void asyncMethod() {
System.out.println("Async method executed.");
}
}
Что с ним не так?
Подсказка: @Async выполняет код в отдельном потоке.
Еще подсказка: магия Spring работает через proxy объекты. Из-за proxy объектов, к слову, магия ломается на финальных классах, в частности в Kotlin, без специальных настроек.
И последняя подсказка: вызов метода того же класса в Java работает через неявное указание this, и этот вызов идет через пул констант класса
https://ru.stackoverflow.com/questions/846457/Пул-констант-в-java
В общем код проблема в том, что asyncMethod будет вызван синхронно, как обычный метод того же класса, proxy код будет проигнорирован. Аналогичная проблема будет и с @Transactional. Проблема называется self execution.
Решений два:
1) простое и поэтому правильное - вызывать метод asyncMethod() из другого класса
2) сделать self injection - внедрить класс сам в себя. Выглядит странно, может сбить с толку, но наверняка может пригодится в отдельных случаях.
P.S. Еще один оффтопик. Код для поста я попросил сгененировать GigaChat и ChatGPT. Первый не справился, второй - справился, но с третьей попытки. И к тому же его пришлось почистить. Указание на название проблемы - self execution - не помогло, у обоих моделей без уточняющих подсказок выдается пример с рекурсивным вызовом асинхронного метода. В общем быстрее написать самому)
#interview_question #spring #java
Stack Overflow на русском
Пул констант в Java
Не раз слышал о так называемом пуле констант в языке программирования Java. Знаю о пуле объектов типа String, пуле для типов Byte, Short, Character, Integer, Long и даже Boolean.
Также знаю, что мы...
Также знаю, что мы...