Spring АйО
8.44K subscribers
304 photos
215 videos
404 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
⚠️ Уязвимость в плагине JetBrains GitHub

Если вы используете плагин GitHub в IntelliJ IDEA или других продуктах JetBrains, советуем обновиться до последней версии и отозвать токены созданные IDEA в своем GitHub аккаунте.

Подробности в статье.

🔗 https://habr.com/ru/companies/spring_aio/articles/820819/
😱12🤔54😐21
🔧 Spring Data findAll антипаттерн

Spring Data Repository отличная концепция, позволяющая нам абстрагироваться от CRUD операций над domain entity. Достаточно объявить пустой интерфейс и унаследовать его, например, от ListCrudRepository или JpaRepository, если мы работем с JPA.


public interface OwnerRepository extends JpaRepository<Owner, Long> {
}


После этого нам сразу будут доступны основные методы работы с entity - save, update, findById, findAllById, findAll, и т.д. Но некоторые из этих методов могут привести к серъезным проблемам с производительностью и памятью, например метод findAll(). Давайте представим, что нам нужно найти всех Owner у которых есть животные c определенным именем и отсортировать по имени владельца. Поскольку мы находимся всего в одном шаге от вызова findAll() метода для «решения» этой проблемы, не пройдет много времени, пока кто-нибудь не предложит следующее решение:



public List<Owner> findOwnerByPetName(Collection<String> petNames) {
return ownerRepository.findAll()
.stream()
.filter(owner -> owner.getPets()
.stream()
.map(Pet::getName)
.anyMatch(petNames::contains)
)
.sorted(Comparator.comparing(Owner::getFirstName))
.toList();
}


Проблема здесь в том, что мы загрузили всю таблицу Post в память и потом начали фильтровать и сортировать данные, вместо того чтобы сделать это с помощью JPQL или SQL запроса за одно обращение к БД и загрузить в память только те данные, которые нам нужны в дальнейшем. Давайте посмотрим как мог бы выглядеть такой метод репозитория:


//derived method
List<Owner> findByPets_NameInOrderByFirstNameAsc(Collection<String> petNames);

//JPA query method
@Query("select o from Owner o left join o.pets pets where pets.name in ?1 order by o.firstName")
List<Owner> findOwnerByPetName(Collection<String> petNames);



Если у нас в репозитории есть метод findAll(), мы должны понимать что рано или поздно, по мере роста команды, им может кто-то воспользоваться. Возможно следует определять базовый интерфейс репозитория вашем проекте самостоятельно и наследовать его от org.springframework.data.repository.Repository и подконтрольно наполнять его методами.

#SpringData #SpringTips
👍235👀3👎2😴2
🤣20😁7👍2🤔1
🕓 Hibernate и спецификация JPA: приключение на 20 минут 24 часа

На прошлой неделе у нас был пост про внезапное падение производительности в Hibernate 6.5 на достаточно простом запросе. А сегодня вы можете прочитать историю этой проблемы от лица Гевина Кинга, создателя Hibernate.

Гевин Кинг рассказал, как возник этот баг, и как он повлиял на спецификацию JPA 3.2.

📚 Подробней читайте на Хабре
👍13🔥4🤯3👏1
По умолчанию в IntelliJ IDEA работают следующие комбинации клавиш:

1) ⌥ + ← (CTRL + ←) – передвинуть каретку к началу слова
2) ⌥ + → (CTRL + →) – передвинуть каретку к концу слова
3) ⇧ + ⌥ + ← (⇧ + CTRL + ←) – выделить слово до его начала
4) ⇧ + ⌥ + → (⇧ + CTRL + →) – выделить слово до его конца
5) ⌥ + ⌫ (CTRL + ⌫) – удалить слово с текущей позиции каретки и до его начала

Но мало кто знает, что эти шорткаты можно сделать еще удобнее!

Настройте их же для режима CamelHumps и IntelliJ IDEA начнёт понимать слова написанные в camelCase!

#IntelliJIDEA #Tooling #HotKeys
This media is not supported in your browser
VIEW IN TELEGRAM
👍187🔥3👏2🥱2🤨1
Разработчики Каркаса Весеннего Ботинка утверждают, что эти фразы имеют смысл:

- "У меня не применяется совет контроллера"
- "Тебе нужно выстрелить событием"
- "Я сделал этот боб главным, чтобы мои анализы не провалились"

My controller advice did not apply
You need to fire an event
I made this bean primary in order to not to fail my tests


Они держат нас за дураков?
😁36👍1👎1🔥1
Внедряем Jakarta Data в Spring приложение

Как Java разработчик, вы, скорее всего, хорошо знаете о шаблоне Repository и связанных с ним возможностях, которые уже предоставлены в популярных фреймворках, таких как Spring Data, Quarkus ORM Panache, Micronaut Data и других. Но у каждого фреймворка есть свои преимущества и ограничения.

Jakarta Data — это новая спецификация Jakarta EE, которая пытается создать универсальные интерфейсы для доступа к реляционным и нереляционным базам данных.


Так выглядит запрос с использованием Spring Data:

public interface PostRepository<Post, UUID> extends JpaRepository {
List<Post> findByStatus(Status status);
}


А вот так с Jakarta Data:

@jakarta.data.repository.Repository
public interface PostRepository extends CrudRepository<Post, UUID> {
@Find
@OrderBy("createdAt")
List<Post> byStatus(Status status);
}


P.S. Выглядит классно, но всё еще не понятно: а зачем это надо, если уже есть Spring Data?). Будем рады обсуждению в комментариях 💬

🔗 https://itnext.io/integrating-jakarta-data-with-spring-0beb5c215f5f (нужен VPN)
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥3😁31
👩‍💻 Spring Boot 3.2: замените свой RestTemplate на RestClient

В мире Spring Boot отправка HTTP запросов к внешним сервисам является весьма распространенной задачей. Традиционно при достижении этой цели разработчики полагались на RestTemplate. Однако, по мере развития Spring Framework, на свет появился новый и более мощный способ обработки HTTP запросов: так называемый WebClient. Spring Boot 3.2 представил нам надстройку над WebClient, которая получила название RestClient.

RestClient предлагает нам более современные и интуитивно понятные способы взаимодействия с RESTful сервисами.

📚 Подробности в статье
Please open Telegram to view this post
VIEW IN TELEGRAM
👍27🔥7👏41
🌿Spring Framework – история проекта и его названия

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

Что же заставило Рода Джонсона (создателя Spring Framework), дать название «Spring» своему фреймворку? Если вы никогда об этом не думали, то эта статья из 2006 года именно для вас!

TL;DR: Название «Spring» было предложено в конце 2002 года и символизировало начало нового периода после «зимы» с традиционным J2EE.

🔗 https://spring.io/blog/2006/11/09/spring-framework-the-origins-of-a-project-and-a-name
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14👍64
🧭 Spring Boot Developer Roadmap

Roadmap для изучения Spring Boot: https://roadmap.sh/spring-boot. Сохраняйте, чтобы не потерять!

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

Будем рады обсуждению в комментариях!

😌 Подписывайтесь на канал: @spring_aio
💬 Вступайте в чат: @spring_aio_chat
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥63👏2👎1
Новый компилятор K2 в Kotlin. Часть 1

В новой статье эксперт сообщества Spring АйОМихаил Поливаха рассмотрит новый компилятор К2 для Kotlin. Сначала он расскажет о том, какие проблемы K2 призван решить, а затем о других минорных улучшениях, которые были сделаны. Гайд по обновлению на новую версию будет опубликован в следующей части этой статьи.

📚 Подробней читайте на Хабре
👍15🔥532
🗓 Еженедельный дайджест №1

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

- Внедряем Jakarta Data в Spring приложение. Обсуждение в комментариях получилось горячим!

- Spring Boot 3.2: замените RestTemplate на RestClient. Кратко объяснили, что такое RestClient и зачем он нужен.

- Spring Framework – история проекта и его названия. Нашли ответ на важный вопрос: "Почему же Spring?" в статье от 2006 года.

- Spring Boot Developer Roadmap. Обсудили, какие технологии должен знать современный Spring Boot разработчик.

- Новый компилятор K2 в Kotlin. Часть 1. Разобрали, чем может похвастаться обновленный компилятор в Kotlin.


И главное, нас уже больше 1000! Спасибо, что вы с нами 😎

😌 Подписывайтесь на канал: @spring_aio
💬 Вступайте в чат: @spring_aio_chat
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥33👍135👏1
🧪Тестирование HTTP-эндпоинтов: MockMvc vs. WebTestClient vs. TestRestTemplate

Spring предлагает различные инструменты для тестирования контроллеров: MockMvc, WebTestClient и TestRestTemplate. И пусть все они служат одной цели (вызову HTTP-эндпоинтов и проверке ответа), между ними есть некоторые различия.

📎 В статье найдете обзор того, где и как использовать эти три класса, а также в чем их отличия (en): https://rieckpil.de/spring-boot-testing-mockmvc-vs-webtestclient-vs-testresttemplate/

TL;DR: основные различия приведены на картинке.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍144🔥3
⚡️ Эффективность Spring-приложений в рантайме. Текущее состояние дел и планы на будущее

Несмотря на то, что данная статья была опубликована более полугода назад, команда Spring АйО по-прежнему считает ее актуальной, важной и интересной.

Себастьян Делюз, контрибьютор Spring Framework, делится обзором усилий команды Spring по оптимизации эффективности приложений во время выполнения. Он рассматривает Virtual Threads, GraalVM Native Image, Project CRaC, Project Leyden и всё это в контексте Spring!

📚 Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/824328/

P.S. Будем благодарны за лайки. Конечно же, если перевод статьи вам понравится 💚
Please open Telegram to view this post
VIEW IN TELEGRAM
👍30🔥632👏1
Spring Tip: Customizer интерфейсы для кастомизации бинов

Одной из главных причин популярности Spring Boot является его способность автоматически конфигурировать (auto-configuration) множество компонентов, существенно упрощая жизнь разработчикам. Однако иногда возникает необходимость слегка подправить настройки этих компонентов без отказа от всех преимуществ автоматической конфигурации.

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


@Bean
CacheManagerCustomizer<ConcurrentMapCacheManager> cacheManagerCustomizer() {
return cacheManager -> cacheManager.setAllowNullValues(false);
}


Аналогичным образом можно настроить и любые другие компоненты:


//Кастомизация свойств Hibernate
@Bean
HibernatePropertiesCustomizer hibernatePropertiesCustomizer() {
return properties -> properties.put("hibernate.integrator_provider",
(IntegratorProvider) () -> List.of(new BeanValidationIntegrator()));
}

//Кастомизация Jackson2ObjectMapperBuilderCustomizer
@Bean
Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);
builder.featuresToEnable(
SerializationFeature.WRITE_ENUMS_USING_TO_STRING,
DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
};
}


Но бывает и такое, что подходящего Customizer интерфейса просто нет. В таком случае, можно использовать BeanPostProcessor для кастомизации уже инициализированных бинов:


//Кастомизация springLiquibase бина
@Bean
BeanPostProcessor liquibaseBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof SpringLiquibase springLiquibase) {
springLiquibase.setContexts("my-context");
}
return bean;
}
};
}


#SpringBoot #SpringTips
Please open Telegram to view this post
VIEW IN TELEGRAM
👍38🔥99
🤔 Разработка ПО действительно так сложна? Или это мы делаем ее такой?

В новом переводе от команды Spring АйО, Siva Katamreddy, девелопер адвокат в AtomicJar (Testcontainers), поделился своими мыслями о популярных в наши дни TDD, Clean, Hexagonal, Onion и Ports & Adapters. Он также постарался ответить на вопрос, который, возможно, волнует не только его: "Действительно ли мы, разработчики, так любим всё усложнять?".

Если сложных задач нет, что нам в таком случае делать? Мы делаем простые вещи сложными и затем решаем сложные проблемы. Не так ли? Мы, разработчики, любим сложность, по крайней мере в начале своей карьеры.


📚 Читать на Хабр: https://habr.com/ru/companies/spring_aio/articles/824838/

😌 Подписывайтесь на канал: @spring_aio
💬 Вступайте в чат: @spring_aio_chat
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥65🤔2🤯1
👨‍💻 Spring Tips: работаем со свойствами

Более миллиона раз разработчики обращались к вопросу на StackOverflow о том, как получить значение из application.properties. Возможно, вы удивитесь (хотя я очень сильно сомневаюсь в этом), но отмеченный как верный ответ с @Value – это не единственный способ. И далеко не всегда самый удобный.

Способ №1: @Value

Аннотация @Value используется для инъекции отдельных значений из файла конфигурации. Например:


@Value("${property.name}")
private String propertyName;


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

Способ №2: @ConfigurationProperties

Аннотация @ConfigurationProperties используется для группировки связанных свойств в объект класса. Свойства могут настраиваться через .properties и .yaml файлы, переменные окружения и т.д.

Типичное использование @ConfigurationProperties может выглядеть следующим образом:


@ConfigurationProperties(prefix = "app")
@Component
@Getter
@Setter
public class ApplicationProperties {
private String name;
}

@SpringBootTest(properties = "app.name=my-app")
class ApplicationPropertiesTest {

@Autowired
private ApplicationProperties applicationProperties;

@Test
void appName() {
var appName = applicationProperties.getName();
assertEquals("my-app", appName);
}
}


Да, нужно будет создать отдельный класс, зато преимуществ у этого подхода относительно @Value довольно много. Перечислим некоторые из них:

– Группировка по префиксу
– Возможность иерархического представления свойств
– Это бин и этим всё сказано :)
@ConfigurationPropertiesBinding
– Кто сможет назвать ещё парочку преимуществ в комментариях?)

Отдельно отметим @ConfigurationPropertiesBinding. Допустим, нам нужно добавить новое свойство version, которое будет представлять класс Version для обработки семантического версионирования (major.minor.patch).


@ConfigurationProperties(prefix = "app")
@Component
@Getter
@Setter
public class ApplicationProperties {
private String name;
private Version version;
}


Для преобразования строкового значения из конфигурации в объект класса Version нам потребуется конвертор, который как раз будет отмечен аннотацией @ConfigurationPropertiesBinding:


@ConfigurationPropertiesBinding
@Component
class SemVerPropertyConverter implements Converter<String, Version> {

@Override
public Version convert(String source) {
return StringUtils.hasLength(source) ? Version.parse(source) : null;
}
}


Пример использования:


@SpringBootTest(properties = {
"app.name=my-app",
"app.version=1.1.0"
})
class ApplicationPropertiesTest {

@Autowired
private ApplicationProperties applicationProperties;

@Test
void appVersion() {
Version version = applicationProperties.getVersion();
assertEquals(1, version.getMajorVersion());
assertEquals(1, version.getMinorVersion());
assertEquals(0, version.getPatchVersion());
}
}


Подробнее про @ConfigurationProperties и @ConfigurationPropertiesBinding вы можете прочитать в документации.

Способ №3: Environment

А если вы хотите обойтись без специальных аннотаций, можно использовать Environment:


@Autowired
private Environment env;

public void someMethod() {
String property = env.getProperty("property.name");
}


#SpringBoot #SpringTips
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥97🤔1🤯1
😁58🔥3👍2👎11
🗓 Еженедельный дайджест №2

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

Тестирование HTTP-эндпоинтов: MockMvc vs. WebTestClient vs. TestRestTemplate. Похолеварили в комментариях на тему постоянных изменений в Spring Framework.

Эффективность Spring-приложений в рантайме. Текущее состояние дел и планы на будущее. Узнали, как обстоят дела с развитием Virtual Threads, GraalVM Native Image, Project CRaC, Project Leyden в контексте Spring.

Spring Boot Tip: Customizer интерфейсы для кастомизации бинов. Рассказали, как можно безболезнено "подкрутить" автоконфигурацию в Spring Boot.

Разработка ПО действительно так сложна? Или это мы делаем ее такой? Таких жарких споров в комментариях на Хабр мы давно не видели.

Spring Boot Tips: работаем со свойствами. Освежили в памяти способы работы со свойствами, их преимущества и недостатки.


😌 Подписывайтесь на канал: @spring_aio
💬 Вступайте в чат: @spring_aio_chat
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥64
🐳 Как управлять запуском различных сервисов в Docker Compose?

Docker Compose предлагает несколько способов управления запуском сервисов. Один из вариантов — создать множество compose.yaml файлов. Главный файл будет содержать все возможные сервисы приложения и его окружения, а другие файлы — импортировать сервисы из основного.

Однако у такого подхода есть недостатки. Во-первых, сложно получить целостное представление о приложении. Во-вторых, создание и поддержка большого количества compose.yaml файлов может быть трудоемкой задачей, особенно если ваша IDE не поддерживает их удобное редактирование.

Решением этой проблемы в Docker Compose являются профили. Этот подход знаком многим разработчикам, работающим со Spring. Профили позволяют гибко управлять запуском сервисов в зависимости от окружения.

Подробнее о Docker Compose профилях можно прочитать в статье (en): https://event-driven.io/en/docker_compose_profiles/

#Docker #DockerCompose
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥511