Spring АйО
8.43K subscribers
304 photos
209 videos
403 links
Русскоязычное сообщество Spring-разработчиков.

Habr: bit.ly/433IK46
YouTube: bit.ly/4h3Ci0x
VK: bit.ly/4hF0OG8
Rutube: bit.ly/4b4UeX6
Яндекс Музыка: bit.ly/3EIizWy

Канал для общения: @spring_aio_chat
Download Telegram
⚡️ Как жить без IntelliJ IDEA? Часть 2. Поддержка Spring

В первой статье из цикла "Как жить без IntelliJ IDEA" мы рассмотрели возможные альтернативы привычной многим IDE.

Во второй статье из цикла команда Spring АйО выяснила, какие есть альтернативы Ultimate в части поддержки Spring и насколько хорошо они справляются со своей задачей.

📚 Читать на Хабре: https://habr.com/ru/companies/spring_aio/articles/854062/
Please open Telegram to view this post
VIEW IN TELEGRAM
121👍10🔥42👎2
🔗 Создание Deep Stubs в Mockito

При юнит-тестировании часто требуется проверить методы, которые используют цепочки вызовов, например, в WebClient из Spring WebFlux.

⚠️ Если задача позволяет, лучше воспользоваться MockWebServer или WireMock для гибкого тестирования HTTP-клиентов. Здесь WebClient выбран лишь из-за своей наглядности и популярности.

Представим клиент, запрашивающий случайную цитату у удалённого сервиса:


public class InspirationalQuotesClient {
private final WebClient webClient;

public InspirationalQuotesClient(WebClient webClient) {
this.webClient = webClient;
}

public String fetchRandomQuote() {
try {
return this.webClient
.get()
.uri("/api/quotes")
.retrieve()
.bodyToMono(String.class)
.block();
} catch (WebClientException e) {
return "Every time a mock returns, a mock a fairy dies.";
}
}
}


Для тестирования такого клиента стандартным способом нужно замокировать каждый вызов в цепочке, чтобы избежать NullPointerException. Это может сделать тест слишком громоздким:


@ExtendWith(MockitoExtension.class)
class InspirationalQuotesClientTest {

@Mock private WebClient webClient;
@InjectMocks private InspirationalQuotesClient cut;

@Test
void shouldReturnInMockingHell() {
WebClient.RequestHeadersUriSpec requestHeadersUriSpec = Mockito.mock(WebClient.RequestHeadersUriSpec.class);
WebClient.ResponseSpec responseSpec = Mockito.mock(WebClient.ResponseSpec.class);

when(webClient.get()).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.uri("/api/quotes")).thenReturn(requestHeadersUriSpec);
when(requestHeadersUriSpec.retrieve()).thenReturn(responseSpec);
when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just("We've escaped hell"));

String result = cut.fetchRandomQuote();
assertEquals("We've escaped hell", result);
}
}


Решение? Deep Stubs в Mockito. С ними можно упростить тест, описав всю цепочку вызовов сразу в конструкции when. Это значительно уменьшит количество кода:


@ExtendWith(MockitoExtension.class)
class DeepStubClientTest {

@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private WebClient webClient;

@InjectMocks private InspirationalQuotesClient cut;

@Test
void shouldReturnQuoteFromRemoteSystem() {
Mockito.when(webClient.get().uri("/api/quotes").retrieve().bodyToMono(String.class))
.thenReturn(Mono.just("Less setup hell - but not better"));

String result = cut.fetchRandomQuote();
assertEquals("Less setup hell - but not better", result);
}
}


Используя параметр answer = Answers.RETURNS_DEEP_STUBS, мы возвращаем заглушку для каждого метода в цепочке. Но помните, что этот подход увеличивает зависимость теста от конкретной структуры вызовов, и любые изменения в цепочке потребуют изменений в тесте.

P.S. А как вы мокируете вызовы внешних API?

Ставьте 🔥 если считаете функциональность полезной.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥41👍974👎4🤯2
📈 Действительно ли ИИ-помощники экономят время разработчиков?

Команда Spring АйО перевела статью об исследовании Uplevel, которое показало, что использование GitHub Copilot не улучшает производительность разработчиков, а наоборот — увеличивает количество ошибок в коде.

Разработчики стали тратить больше времени на проверку ИИ-сгенерированного кода, что снижает ожидаемую экономию времени. Хотя компании активно внедряют ИИ-инструменты, их реальная польза для повышения продуктивности остается под вопросом.

📚 Читать на Хабре: https://habr.com/ru/companies/spring_aio/articles/854624/
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍23🔥753
🧩 Исключение строк из уникальных индексов

Представьте, что вам нужно поддерживать уникальность данных, например, адресов электронной почты в таблице базы данных. Но что делать, если в таблице есть строки, помеченные как удаленные, например, с помощью дополнительного поля deleted_at? При этом важно учитывать, что удаленные данные тоже находятся в таблице, поэтому в поле с почтой будут дубли, сделать уникальный индекс не получится. Здесь на помощь приходят partial индексы.

Partial индекс позволяет задать условие (например, WHERE deleted_at IS NULL), чтобы включать только нужные строки и игнорировать удаленные. Эта функция доступна в PostgreSQL, где можно исключать строки с soft delete, сохраняя требуемую уникальность и оптимизируя размер индекса.

⚠️ Советуем сделать бэкап своей БД перед выполнением запросов во избежании потери данных

Реализация
В PostgreSQL добавление уникального индекса для активных пользователей выглядит так:

CREATE UNIQUE INDEX users_email_uniq ON users (
email
) WHERE deleted_at IS NULL;

В этом случае строки, у которых deleted_at не задан, включаются в индекс, а остальные игнорируются, что делает индекс более компактным и эффективным.

Для MySQL требуется обходной путь, так как partial индексы в нем не поддерживаются. С использованием конструкции IF(deleted_at, NULL, 1) можно эмулировать аналогичное поведение. Пример индекса:


CREATE UNIQUE INDEX users_email_uniq ON users (
email,
(IF(deleted_at, NULL, 1))
);


Здесь NULL используется чтобы исключить удаленные строки из индекса: строки, помеченные как удаленные, получают значение NULL и не конфликтуют с другими значениями.

Как это работает?
Есть некое свойство базы данных, что значения NULL не рекомендуется сравнивать ни с чем, используя ANSI SQL стандартные операторы (=, !=, <> и т.д.), т.к. сравнение приведёт к unknown. Получится так, что два значения (example@example.com, null) в индексе могут спокойно существовать, в то время как два значения (example@example.com, 1) будут конфликтовать. Это свойство позволяет обойти ограничение MySQL и реализовать функциональность partial индекса. Например, строка с адресом foo@example.com, если пользователь помечен как удаленный, получит значение индекса (foo@example.com, NULL) и не создаст конфликта, даже если аналогичная строка существует. Такая стратегия помогает соблюсти уникальность данных, сохраняя логическую целостность таблицы и избегая лишних конфликтов в MySQL.

Преимущества частичных индексов
Кроме того, partial индексы сокращают объем данных, включаемых в индекс, тем самым экономя место и ускоряя операции поиска. PostgreSQL предлагает удобный и простой способ реализации частичных индексов, в то время как MySQL требует определенных обходных решений.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍35🔥136🤩1
🧠 AI-ассистент со Spring AI (Часть 2)

Не так давно мы публиковали первую часть статьи по написанию AI-ассистента со Spring AI. В продолжении статьи автор углубляется в возможности генерации с поддержкой поиска (RAG), чтобы LLM могла учесть некоторую контекстуальную информацию данных, превоначально невходившую в ее обучающую выборку.

В новом переводе от команды Spring АйО рассматривается польза Spring AI и векторной БД, благодаря которым система не просто сопоставляет ключевые слова, но и понимает смысловые запросы пользователей, делая взаимодействие с приложением еще более естественным.

📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/855398/
👍11🔥84
🗓 Еженедельный дайджест №19

Для тех, кто был слишком занят на неделе или просто пропустил некоторые посты, публикуем дайджест!

Как жить без IntelliJ IDEA? Часть 2. Поддержка Spring посмотрели на альтернативы IntelliJ IDEA Ultimate в части поддержки Spring и провели их анализ

Создание Deep Stubs в Mockitoпознакомились с мокированием целой цепочки вызовов

Действительно ли ИИ-помощники экономят время разработчиков?узнали, насколько полезен ИИ для разработчкиков в наши дни

Исключение строк из уникальных индексоврассмотрели способ включения только нужных строк при создании индекса БД

AI-ассистент со Spring AI (Часть 2)ознакомились со второй частью серии статей про внедрение AI-ассистента с помощью Spring AI

😌 @spring_aio
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥54
⚙️ Давайте использовать OpenTelemetry со Spring!

Команда Spring АйО перевела статью, раскрывающую преимущества использования OpenTelemetry для мониторинга и трассировки Spring Boot приложений.

В статье показано, как интеграция с OpenTelemetry с использованием OTLP и других компонентов позволяет легко встроить стандартизированный сбор метрик, логов и трассировок в экосистему Spring.

📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/855868/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍23🔥64
⭐️ CascadeType.ALL и @ManyToMany

Использовать CascadeType.ALL для @ManyToMany не рекомендуется, так как это может привести к непредсказуемым результатам во время удаления JPA сущностей. Вместо этого следует использовать CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST и CascadeType.REFRESH.

Подробнее об этом рассказано в отдельном видео!

😉 СМОТРЕТЬ НА YOUTUBE
😄 СМОТРЕТЬ В VK ВИДЕО
🥰 СМОТРЕТЬ НА RUTUBE
Please open Telegram to view this post
VIEW IN TELEGRAM
👍23🔥74
🗑 Сборка мусора в Java. Часть №1. Обзор сборщиков мусора и их различий

Команда Spring АйО перевела и адаптировала доклад "Garbage Collection in Java: The progress since JDK 8" Стефана Йоханссона (Stefan Johansson) с последнего Devoxx Belgium.

Доклад получилось поделить на две статьи. В первой вы узнаете об основах работы сборки мусора в Java, различных сборщиках мусора, а также об их особенностях, плюсах и минусах.

📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/856468/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥125
Forwarded from Amplicode
👀 Ищем энтузиастов Spring Data JDBC!

В следующем мажорном релизе мы планируем расширить поддержку Spring Data, реализовав поддержку Spring Data JDBC и добавив возможности, которые ранее были доступны только для Spring Data JPA.

Придерживаясь CDD (Community Driven Development), команда Amplicode хочет услышать мнение разработчиков, которые на постоянной основе работают с Spring Data JDBC.

Если вы хотите:
– Принять участие в развитии продукта
– Поделиться своим опытом и рассказать о задачах и трудностях, с которыми сталкиваетесь, работая с Spring Data JDBC

то заполните короткую форму, и мы свяжемся с вами в ближайшее время!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥21👍94👌1
⚡️ Liquibase теперь собирает статистику использования

Liquibase объявила о включении анонимного сбора данных в версии 4.30.0 и выше для пользователей Open Source версии.

Телеметрия активируется только при запуске команд и по умолчанию отключена только для пользователей Pro версии. Компания подчеркивает, что данные обезличены и не передаются третьим лицам.

Сбор статистики позволит команде лучше понять, как используется продукт, и повысить его качество, выявляя популярные команды, частые ошибки и оптимизируя поддержку различных баз данных.


Однако, если вы не хотите делиться статистикой, то можете её выключить, используя:
* Параметр --analytics-enabled=false в CLI
* Глобальную настройку liquibase.analytics.enabled: false в liquibase.properties файле
* Или переменную окружения LIQUIBASE_ANALYTICS_ENABLED=false

#breaking_news #liquibase
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯52👍2182🔥2
Какой системой версионирования баз данных пользуетесь в продакшене?
Anonymous Poll
24%
Flyway
64%
Liquibase
3%
Пользуюсь собственным велосипедом
9%
Не пользуюсь
1%
Другое, напишу в комментарии
👍84🔥4
🗓 Еженедельный дайджест №20

Для тех, кто был слишком занят на неделе или просто пропустил некоторые посты, публикуем дайджест!

Давайте использовать OpenTelemetry со Spring! показали преимущества использования OpenTelemetry для мониторинга и трассировки Spring Boot приложений

CascadeType.ALL и @ManyToMany представили видео, в котором показали, почему не рекомендуется использовать CascadeType.ALL для @ManyToMany

Сборка мусора в Java. Часть №1. Обзор сборщиков мусора и их различийузнали основы работы сборки мусора в Java, а также особенности различных сборщиков мусора

Liquibase теперь собирает статистику использованиярассказали о том, что начиная с версии Liquibase 4.30.0 и выше для пользователей Open Source версии сбор аннонимизированной статистики будет включен по умолчанию (как её выключить тоже рассказали :))

😌 @spring_aio
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍75👌2
🛡 Поддержка RestClient для OAuth2 в Spring Security 6.4

Команда Spring АйО перевела статью, в которой Steve Reisenberg рассказал о множестве полезных улучшений для работы с OAuth2 в Security 6.4.

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

📚Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/857664/
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥25👍197